1

I just read this post on SO, that discusses where in memory, STL vectors are stored. According to the accepted answer,

vector<int> temp;

the header info of the vector on the stack but the contents on the heap.

In that case, would the following code be erroneous?

vector<int> some_function() {
  vector<int> some_vector;
  some_vector.push_back(10);
  some_vector.push_back(20);
  return some_vector;
}

Should I have used vector<int> *some_vector = new vector<int> instead? Would the above code result in some code of memory allocation issues? Would this change if I used an instance of a custom class instead of int?

Community
  • 1
  • 1
  • 1
    That code in `some_function` is good and will work fine. It will copy (using the copy-constructor) the contents of `some_vector` into the receiving vector. – Some programmer dude Dec 18 '13 at 11:54
  • Your function is fine, and avoid using dynamically allocated memory unless it's really required and you know what you're doing. – Violet Giraffe Dec 18 '13 at 11:58
  • @JoachimPileborg: Actually, I think it will *move* the vector out. Wouldn't it? – yzt Dec 18 '13 at 12:12
  • @yzt In a C++11 compiler, yes it probably would. – Some programmer dude Dec 18 '13 at 12:18
  • Returning the vector by copy will be slower though, right? I mean it has to copy all the contents into the receiving vector. If you are concerned about speed, move the vector into a pool and return the pointer to it. – Giel Dec 18 '13 at 14:33
  • @Giel: Actually, even with a pre-C++11 compiler and STL, the compiler will quite likely use "Return Value Optimization" (RVO) which will eliminate the copy altogether. – yzt Dec 19 '13 at 11:23
  • @Giel It's usually even more efficient to pass by value. Check [this link](http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/) – MikMik Dec 20 '13 at 11:47
  • @yzt/MikMik Thanks for the link, very interesting. in the above case I can imagine it doing this optimization. Although imagine a vector that got filled in Init() (100 items in vector myVec). Then GetMyVec() { return myVec; } is called. that will create a copy (timewaste). instead returning a reference/pointer will be faster, right? – Giel Dec 22 '13 at 22:17
  • @Giel: Not necessarily, and not always. There are "pointer aliasing" issues here that might (and often do) prevent the compiler from doing some optimizations. Not to mention the fact that returning pointers out from functions can create a lot of problems about lifetime and ownership management. All in all, if this is really performance-critical (I'm talking micro- and nano-seconds here) *then measure it*! If not, just go with the more elegant and readable solution. – yzt Dec 22 '13 at 23:23
  • @Giel: Also, *moving* a vector around (as opposed to *copying* it) is an O(1) operation, pretty much as fast as copying a pointer to it. (After all, a vector is probably just 24 bytes in size, vs. 8 bytes for a pointer.) And all the optimizations in place for "copy elision" (e.g. RVO) also work for "move elision"! – yzt Dec 22 '13 at 23:31
  • @yzt: yes copy and move speeds might be in the same ballpark, but a move can be optimized since the data only needs to be in 1 place. so it can do the optimization with the preallocation and allocating it in that memory, for a copy somehow it needs to store it in 2 locations, so it seems to me that is unoptimizable. Also, how is the vector 24 bytes in size? it depends on its contents. It still looks to me that this optimization is only valid for in-place made vectors that are returned by value – Giel Dec 22 '13 at 23:47
  • @Giel: Either I don't understand what you're saying, or you need to learn a bit more about memory layouts and object copying/moving in C++. Also, in my last comment, I was referring to moving vs. *pointer* copying. And `sizeof(std::vector)` is probably 24 bytes in a 64-bit build; that's the amount of data that needs to be copied when the vector is being *moved*. The external memory allocated for the vector contents doesn't need to be copied for a *move*. (As I said, it is possible that I'm misunderstanding your point, but this is not the place to continue this discussion.) – yzt Dec 23 '13 at 08:57

3 Answers3

8

Your code is precisely fine.

Vectors manage all the memory they allocate for you.

It doesn't matter whether they store all their internal data using dynamic allocations, or hold some metadata as direct members (with automatic storage duration). Any dynamic allocations performed internally will be safely cleaned-up in the vector's destructor, copy constructor, and other similar special functions.

You do not need to do anything as all of that is abstracted away from your code. Your code has no visibility into that mechanism, and dynamically allocating the vector itself will not have any effect on it.

That is the purpose of them!

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
2

If you decide for dynamic allocation of the vector, you will have really hard time destroying it correctly even in very simple cases (do not forget about exceptions!). Do avoid dynamic allocation at all costs whenever possible.

In other words, your code is perfectly correct. I would not worry about copying the returned vector in memory. In these simple cases compilers (in release builds) should use return value optimization / RVO (http://en.wikipedia.org/wiki/Return_value_optimization) and create some_vector at memory of the returned object. In C++11 you can use move semantics.

But if you really do not trust the compiler using RVO, you can always pass a reference to a vector and fill it in inside the function.

//function definition
void some_function(vector<int> &v) { v.push_back(10); v.push_back(20); }

//function usage
vector<int> vec;
some_function(vec);

And back to dynamic allocation, if you really need to use it, try the pattern called RAII. Or use smart pointers.

1

It is not important where internally vectors define their data because you return the vector by copy.:) (by value) It is the same as if you would return an integer

int some_function()
{
   int x = 10;
   return x;
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335