Allocate Struct Memory

Pages: 12
I can allocate memory for a string simply enough --

char* str=(char *)malloc( (mysize + 1) * sizeof(char) );

but what if I do this...

1
2
3
4
struct MYSTRUCT {
char * str1;
char * str2;
};


Now what if I have, say, four or five different items for my struct, so that I need to allocate memory for str1 and str2 four or five times?

Do I iterate through each one-by-one and indivually allocate memory for str1 and str2 on each pass?

For example, say that I have to deal with 5 instances where I will need to put data in str1 and str2 on the first item, then put data into str1 and str2 on the second item, and so on? Do I simply iterate through it and allocate on each iteration, or what?

I hope this is clear. If not, I'll try to explain better.
Last edited on
Initialization of members is done in the constructor, which will be called for each element of an array if you create it properly (with new[]). std::string does this automatically, which is what you should be using.
Yeah, but I don't want to use that. I want to stick with straight C Win32 API.
Then you're on the wrong forum.
+1 @Athar. If you don't want to use C++, you have to do the duplication of everything. This is why we use C++ and not C. :-)
Okay, well how would you do it in C++ by using new[]? IOW,

LPSTR str=new char[mysize];

so that if I do this...

1
2
3
4
5
6
struct MYSTRUCT {
char *str1;
char *str2;
];

MYSTRUCT ms;


Now how would I allocate memory to str1 and str2 if I need to through it five times? Do I simply iterate throug it, such as...

1
2
ms.str1=new char[mysize];
ms.str2=new char[mysize];


and then do this five times for each iteration?

You see, it's the same question.

Or can I allocate for the whole structure itself? That's what I'm not understanding.
Last edited on
Erm, no.

You'd do it like this:

1
2
3
4
5
6
7
8
struct MyStruct
{
  MyStruct() : str1(mysize), str2(myself) {}
  std::string str1;
  std::string str2;
};

vector<MyStruct> instances(5);
Or can I allocate for the whole structure itself?

If you have five instances with non-shared (read: non-static) members, you'll need to allocate whatever is needed for each instance. Which is done by the constructor in C++.
I'm not clear what you mean by the constructor. I know that there is a contructor in a class, but I'm not declaring a class of any sort. So what you're telling me I don't understand.

Let's say I am going to gather five different two-string combinations to match str1 and str2 in my struct above. I need memory five times each for each of the two strings in my structure.

I am going to gather the data for a two-string combo once, then a second time, and so on for five tmes. Each string combo one will be placed in str1 and str2 respectively of my structure, for five times each, but I don't know the size of each string until I get it, so that's why I need to allocate memory for str1 and str2, only five times because I will be encountering 5 different instances that the memory needs to be allocated.

So whether I am using malloc() or new[] doesn't seem to me to make any difference. If it does, I don't understand why. I don't about any constructor being involved in this. Please tell me what you mean by this.

Last edited on
It's more normal to allocate buffers for each string member of the struct, as you're doing above with new. But with malloc.

malloc(sizeof(struct MYSTRUCT)) just allocates enough space for the two pointers; not their buffers.

You can avoid reallocating each time if you make the buffer big enough to start with, and then use strcpy. Or you could guess, and then resize the buffer if its too small for a particular string.

If you're coding C, you might also be interested in strdup(). This allocates a buffer using malloc and copies a string into it. You free the memory it returns with free.

If you do allocate on each pass, you'll need to free on each pass, too.

Or you can allocate a single big block and then init the pointer to point (back) into the same buffer. This approach only really works with a buffer size big enough to be used.

1
2
3
4
size_t bufferSize = 200;
struct MYSTRUCT* ptr = (struct MYSTRUCT*)malloc(sizeof(struct MYSTRUCT) + 2 * bufferSize);
ptr->str1 = (char*)ptr + sizeof(struct MYSTRUCT);
ptr->str2 = ptr->str1 + bufferSize;


Last edited on
I know that there is a contructor in a class, but I'm not declaring a class of any sort.

Eh? MyStruct is a class.
The problem with this code --

1
2
3
4
5
6
7
8
struct MyStruct
{
  MyStruct() : str1(mysize), str2(myself) {}
  std::string str1;
  std::string str2;
}

vector<MyStruct> instances(5);


is twofold...

I don't KNOW the size of "myslze" in the struct above. I won't know that until later.

Secondly, I don't care to use vector<>. This forum says Windows and C++. I don't have to use vector<> to still be coding C++.
I don't KNOW the size of "myslze" in the struct above. I won't know that until later.

Then just don't preallocate any storage?! std::string cares take of storage and allocates as much as is needed when you assign it a new string.

I don't have to use vector<> to still be coding C++.

If you have a fixed size of 5, you can use std::array instead.
Well, we may be cross-posint here, but first off, I never knew that a struct was a class. I thought it was struct. Secondly, I've never known that a struct has a constructor. What is the constructor in a struct?
struct and class both declare a class. The only difference is that when using the struct keyword members are public by default and when using class they're private by default. That's all.
Ah... okay, I remember reading that now, I think.

In any ase, what it boils down to is that since I won't know the size of each string in each two-string combo, I'm going to have to iterate through it and allocate through each iteration.

The only way I could think of would be to allocate for an entire structure, which was bascially what I think was leaning toward in my first question, but perhaps I hadn't through it through well enough.

Anyway, I think I've got it figured out. Thanks for the ideas.
andywestken:
It's more normal to allocate buffers for each string member of the struct, as you're doing above with new.


I think this is the confirmation I needed.

But I don't really understand this statement --

malloc()... just allocates enough space for the two pointers; not their buffers.


What's the difference?
Last edited on
Also, someone not too long ago explained the advantages of new[] over malloc() with regard to certain managment and cleanup functions. What are the main advantages again?

I'm more or less deciding to become a new[] "convert", but I'd like to be able to tell somebody why I did this if anybody ever asks, like when I'm in the check-out line that grocery store and the guy behind me say, "do you use new[] or malloc(), and why?" -:)
Last edited on
One more thing...

From what I understand, new[] doesn't have the capability to reallocate memory, as does malloc(). Is that true?

If it is then malloc() is still part of C++ unless there's some other way to do this.

Is there another way to reallocate memory with a strictly C++ standard?

EDIT: Stephen Prata agrees that malloc() is still a C++ function. Here's a verbatim quote from his book "C++ Primer Plus", Fifth Edition --

"In C, you can allocate memory with the library function malloc(). You can stilll do so in C++, but C++ has a better way : the new operator." p. 150

Since everybody wants to get technical. -:)
Last edited on
Use new over malloc() because new makes sure that objects constructors are run.

A std::string will reallocate memory as appropriate:
1
2
3
4
5
struct MYSTRUCT
{
    std::string str1;
    std::string str2;
};

I am not sure why you don't want to use a std::vector? It would probably save you some work.
Pages: 12