tags:

views:

154

answers:

6

Hello. My question is simple. When I use STL containers, do they copy the value I store there (by using copy constructor) or not? What if I give them array of characters (char *) instead of string instance? How do they behave? Is guaranteed that information will be stored in heap instead of system stack?

Thanks for answers.

+5  A: 

They copy the value. Most (all?) containers require that a copy constructor and an assignment operator are defined.

If you give them a char*, they copy the pointer, not the value pointed to. So then it would be your responsibility to make sure that the string itself is not destroyed while it is still in use, and gets destroyed when it is no longer necessary.

Thomas
To be clear, the containers copy the value of the element template argument type. If the container is defined to contain "int*", it'll copy the pointers to integers, not the underlying integers.
David Gladfelter
+3  A: 

They always make copies. If you create a vector<char *> then it will copy the char* you push into it. However, it will not copy the string of chars the pointer points to. If that string was dynamically allocated, you probably have a leak, which is why vector<string> is usually infinitely preferable.

anon
+1  A: 

They always copy when you put in them. If you give them a pointer then they copy the pointer. The Data that pointer points to is not affected. Note, it's not recommended to put raw pointers into stl containers, because it's easy to lose track of them and leak memory. STL containers weren't designed to help you with raw pointers. If you want to use pointers in STL containers, consider shared_ptr's from boost to wrap them.

Chris H
+7  A: 

Values in STL containers are stored by-value. If you have a vector like this:

class BigObject
{
...
};

vector<BigObject> myObjs;
myObjs.push_back(obj1);
myObjs.push_back(obj2);
...

The vector will make a copy of the object you're pushing in. Also in the case of a vector, it may make new copies later when it has to reallocate the underlying memory, so keep that in mind.

The same thing is true when you have a vector of pointers, like vector<char*> -- but the difference here is that the value that is copies is the pointer, not the string it points to. So if you have:

vector<char*> myStrings;
char* str = new char[256];     // suppose str points to mem location 0x1234 here
sprintf(str, "Hello, buffer");
myStrings.push_back(str);
delete [] str;

...the vector will get a copy of the pointer. The pointer it gets will have the same value (0x1234), and since you deleted that pointer after pushing in the pointer, your vector contains a wild pointer and your code will eventually crash (sooner than later, hopefully).

Which, by the way, could have been avoided if instead of using char*s you used strings:

typedef vector<string> strings;
strings myStrings;
myStrings.push_back("Hello, buffer");
John Dibling
+1  A: 

You've already gotten a number of answers pointing out that when you put data into a container, it's put there by value, so what goes into the container is a copy of your original data.

There is one sort-of exception to this rule though: std::list has a splice member that allows you to insert a portion (or all) of one list into another list. In this case, the data is normally moved rather than copied -- at least normally, the splicing is done by manipulating the pointers, so the nodes that were in one list are transplanted to the other list.

The exception to that is if the two lists use different allocator types. In this case, I believe splice has to allocate new nodes, copy data, then release the old nodes. Then again, this is a fairly obscure corner case -- most people never implement their own allocator types.

Jerry Coffin
A: 

Furthermore, if you don't want the overhead of copying entire objects and don't like ht headaches associated with using pointers, you can use boost::shared_ptr inside a vector to ensure that the memory dynamically allocated will be released only when it is no longer being referenced.

Trent