tags:

views:

328

answers:

5

After a lot of investigations with valgrind, I've made the conclusion that std::vector makes a copy of an object you want to push_back.

Is that really true ? A vector cannot keep a reference or a pointer of an object without a copy ?!

Thanks

+12  A: 

Yes, std::vector stores copies. How should vector know what the expected life-times of your objects are?

If you want to transfer or share ownership of the objects use pointers, possibly smart pointers like shared_ptr (found in Boost or TR1) to ease resource management.

Georg Fritzsche
learn to use shared_ptr - they do exactly what you want. My favorite idiom is typedef boost::shared_ptr<Foo> FooPtr; Then make containers of FooPtrs
pm100
@pm100 - Do you know `boost::ptr_vector` ?
Manuel
According to http://www.boost.org/doc/libs/1_42_0/libs/ptr_container/doc/ptr_vector.html, it's a raw pointer, not a smart one. Dangerous.
Steven Sudit
I also like to use `class Foo { typedef boost::shared_ptr<Foo> ptr; };` to just write `Foo::ptr`.
Rupert Jones
@manuel - no i do not - i will look. @rupert nice style but it has one weakness, I must own the class
pm100
@Steven. Not dangerous at all. ptr_vector holds the ownership of the object.
Nemanja Trifunovic
ptr_vector seems to have some corner case advantages but is non shared - too dangerous compared to the 'fire and forget' behavior of shared_ptrs
pm100
@Rupert Jones, pm100 - I've been using `ptr_vector` for quite a while and I've never felt the need for shared ownership
Manuel
@Nemanja: You're right. The description claims it's a raw pointer, but the header clearly shows auto_ptr is being used. Bad documentation!
Steven Sudit
@pm100 - `shared_ptr` is not exactly fire and forget. See http://stackoverflow.com/questions/327573/ and http://stackoverflow.com/questions/701456/
Daniel Earwicker
shared_ptr is good if you have shared ownership, but it is generally overused. unique_ptr or boost scoped_ptr make much more sense when the ownership is clear.
Nemanja Trifunovic
"scoped_ptr cannot be used in C++ Standard Library containers. Use shared_ptr if you need a smart pointer that can." http://www.boost.org/doc/libs/1_41_0/libs/smart_ptr/scoped_ptr.htm
Steven Sudit
+4  A: 

std::vector always makes a copy of whatever is being stored in the vector.

If you are keeping a vector of pointers, then it will make a copy of the pointer, but not the instance being to which the pointer is pointing. If you are dealing with large objects, you can (and probably should) always use a vector of pointers. Often, using a vector of smart pointers of an appropriate type is good for safety purposes, since handling object lifetime and memory management can be tricky otherwise.

Reed Copsey
it doesnt depend on the type. It always makes a copy. If its a pointer is makes a copy of the pointer
pm100
You're both right. Technically, yes, it always makes a copy. Practically, if you pass it a pointer to the object, it copies the pointer, not the object. Safely, you should use an appropriate smart pointer.
Steven Sudit
Yes, it's always copying - However, the "object" the OP is referring to is most likely a class or struct, so I was referring to whether it's copying the "Object" depends on the definition. Poorly worded, though.
Reed Copsey
+6  A: 

Yes, std::vector<T>::push_back() creates a copy of the argument and stores it in the vector. If you want to store pointers to objects in your vector, create a std::vector<whatever*> instead of std::vector<whatever>.

However, you need to make sure that the objects referenced by the pointers remain valid while the vector holds a reference to them (smart pointers utilizing the RAII idiom solve the problem).

Alexander Gessler
+1 for mentioning the need for smart pointers
Steven Sudit
+3  A: 

Not only does std::vector make a copy of whatever you're pushing back, but the definition of the collection states that it will do so, and that you may not use objects without the correct copy semantics within a vector. So, for example, you do not use auto_ptr in a vector.

Liz Albin
A: 

if you want not the copies; then the best way is to use a pointer vector(or another structure that serves for the same goal). if you want the copies; use directly push_back(). you dont have any other choice.

rahmivolkan