Hi! This is a pretty straight-forward question. I want to make sure I understand when to allocate dynamic memory on the heap vs. instantiating an object on the stack. If I have a vector of CMyDataStruct objects, I am wondering what is the best way to store and access this information. For example, I could store this information on the stack as follows:
This could take up a lot of space and call the copy constructor of each object in the vector whenever I assign an object to it, which doesn't seem very efficient to me. On the other hand, I could store it on the heap:
1 2 3 4 5 6 7 8 9 10 11 12 13
std::vector someFunction()
{
std::vector<CMyDataStruct*> vec;
for(int i = 0; i < 10; i++)
{
CMyDataStruct myDataStruct = new CMyDataStruct();
myDataStruct->prop1 = "property";
vec.push_back(myDataStruct);
}
return vec;
}
and I could even do...
1 2 3 4 5 6 7 8 9 10 11 12 13
std::vector* someFunction()
{
std::vector<CMyDataStruct*> vec = new std::vector<CMyDataStruct*>;
for(int i = 0; i < 10; i++)
{
CMyDataStruct myDataStruct = new CMyDataStruct();
myDataStruct->prop1 = "property";
vec->push_back(myDataStruct);
}
return vec;
}
I am concerned about memory. Perhaps right now, CMyDataStruct may not consume a lot of memory, but maybe as the class grows it will. So I'm trying to understand what the best practice is for a scenario such as this. One issue I can see right away is that if I allocate memory for these 10 myDataStruct objects, I am responsible for cleaning up that memory later, which could be a potential memory leak. On the other hand, storing the actual objects in the vector could potentially take up a lot of space on the stack and call each objects copy constructor every time I grab the item from the vector.
I guess my goal is simply to optimize speed and memory effectively. What seems to be the best practice for this type of scenario? Thanks!
Only use dynamic allocation when you have to. It's slower, it can lead to memory leaks, and as for what you were saying about it calling the constructor when you allocate on the stack, it calls the constructor when you allocate on the heap too, every time an object is created a constructor is called, the only difference is how the data is stored in your vector. You either store the objects themselves, or pointers to them.
...every time an object is created a constructor is called, the only difference is how the data is stored in your vector
Right, but there is a difference in the following:
1 2
// vec[0] is a CMyDataStruct object. copy constructor called.
CMyDataStruct myDataStruct = vec[0];
vs.
1 2
// vec[0] is a CMyDataStruct * object. No copy constructor called
CMyDataStruct *myDataStruct = vec[0];
From your statement above, taking the hit of the copy constructor is better than allocating memory dynamically on the heap correct? I'm probably reading into this to much but I want to make sure I understand this correctly.
call each objects copy constructor every time I grab the item from the vector.
Only when you pushed, not when you access it. vec[i].some_method(); vec[i] will return a reference, not a copy.
I am responsible for cleaning up that memory later, which could be a potential memory leak
Use smarts pointers then
Edit: About the second post, what are you saying there?
Those two codes are not equivalent. You call the copy constructor because you will have one more object
No copies:
1 2
T &obj = vec[0]; //std::vector<T>
T *ptr = vec[0]; //std::vector<T*>
This does not take into account NRVO.
Even in the first case no copy constructor will be called because compilers will apply NRVO here.
This works in all "simple" cases (i.e. one return path, no exceptions).
However, one should keep in mind that the C++ standard does not dictate that compilers have to perform NRVO in this case, it merely allows for it.