I've got the famous problem, that I like to create an instance of class "parent" which has lot's of members, e.g. other child classes, but to this point of time I don't know how many of them I will need later:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
class parent
{
public:
child* child;
parent(int child_count);
};
int main(int argc, char** args)
{
parent test(20);
return 0;
}
parent::parent(int child_count)
{
this->child = new child(this)[20]; // doesn't work like that, although I read in many topics that I'd have to do it this way...
}
Instead, it only works when I declare "child" as array directly in class declaration, and then initialize it like that:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
class parent
{
public:
child* child[100]; // bad, because I'd like to allocate only as much memory as needed
parent(int child_count);
};
parent::parent(int child_count)
{
for(int i = 0; i < child_count; i++)
{
this->child[i] = new child(this); works... but WHY??
}
}
Why do I have to do it this way? I'd really prefer the first way because it looks much better and I wouldn't need to allocate much memory even if I don't need it later..
Any solutions?
[edit]
The one caveat is that you still need to release memory if your parent 'owns' the children, otherwise you'll have a memory leak (like in my examples above). Depending on your needs, a shared_ptr or unique_ptr may be useful.
1 2 3 4 5
class parent
{
public:
std::vector <std::unique_ptr <child>> children;
...
And your vector can still grow as you wish at run-time.
Further comments: I imagine the code up there is affected, as it is not a parent-child relationship by any means, "this" is overused, and variable naming is impossible.
first of all, thank you all for your support!
I didn't know std::vector till now, but it sounds interesting. That's why I googled it and found some benefits (easy to handle, dynamically size growth etc.) but also a disadvantage: it needs much more memory (according to googles search results).
When I understood that right, std::vector allocates more memory then needed, and so it can additionally store new array elements ("growing").
What I'm asking myself then is, where is the difference between using std::vector and declaring child* children[100];? I mean, my motivations not to do it that way were not to allocate more memory then needed, but with std::vector I'll have the same problem, or am I wrong?
Otherwise, I recognize that almost every reply to my question contains std::vector as suggestion, so I think it's still better to use it then declaring an array with fixed and very big size...
What do you mean?
@MiiNiPaa: this->child = new Child[5] {{this}, {this}, {this}, {this}, {this}};
How could I manage this with a loop? I mean, initializing 100 child object with that method would be really hard to type by hand {{this}, {this}........}...
it needs much more memory (according to googles search results).
What? At most 32 bytes per vector.
my motivations not to do it that way were not to allocate more memory then needed, but with std::vector I'll have the same problem, or am I wrong?
You can specify size of the vector when creating it. After that it will get more memory only when needed. Additionally it is safe: it manages memory and release it. You cannot forget about this, you should not worry about exception thrown before you have a chance to release memory, it is easy to extend your class if you need, It provides many useful functions.
How could I manage this with a loop?
If your Child class have an assigment operator and default constructor, you can do:
1 2 3 4 5
this->child = new Child[100]; //default constructs 100 objects
for(std::size_t i = 0; i < 100; ++i)
child[i] = Child(this); //Creating a temporary and copy-assign it. 100 times
//Whole affair is 3 times as slow as vector one.
//With some changes we can improve it to 2x
A vector is the preferred container in C++ because, in comparison to arrays, vector array control and management is substantially better and easier to implement.
Vectors give you more flexibility, but admittedly real parents don't have more than, lets say, 25 kids?? 100 would be very unusual even for ...
A good summary of the pros and cons is:
http://www.cplusplus.com/reference/vector/vector/
PS there are other standard containers and a <map> might be useful.
@MiiNiPaa:
Hehe well, you convinced me with that :)
I'm really interested in how std::vector manages that all?! How can it dynamically add memory to an array without copying it to a new, bigger one? Or is it that way? Then I'm wondering how it can still be faster 3 or 2 times then the way you specified up there...
You can specify size of the vector when creating it
Depending on your needs. If you need exactly x values initialized to some value y, you probably want to specify it when creating vector.
Then I'm wondering how it can still be faster 3 or 2 times then the way you specified up there...
With arrays: you are creating n default-initialized objects (1). Creatint n custom initialized objects (2) and assigning them to array elements (3). You can simplify it creating one object and reusing it throughout the loop, eliminating (2).
Vector: creates uninitialized storage (neglible), value initializes each element (1).
You can do this too, but it will be more complexthat simply declare an array, so it is better to leave management to something which is already created, tested and optimized.
How can it dynamically add memory to an array without copying it to a new, bigger one?
It is actually reallocates it. That is why you want to move-optimize your classes if you want to store them in containers. But, you do not use dynamic growing abilities of vector. You just need fixed size something to store values in.