Lifecycle of objects passed by reference to STL containers
I'm an experienced coder, but am still relatively new to the STL, and have just come across this problem:
As far as I'm aware, STL containers aren't meant to copy the objects which they contain, or otherwise affect their lifecycles, yet experimentally I'm seeing different results.
In particular, string classes, which are meant to zero out the first character of their underlying storage upon destruction, are still accessible if they are stored in a 开发者_运维知识库container before they go out of scope. For instance, consider the following example:
using namespace std;
queue<string> strQueue;
const char *genStr(int i)
{
ostringstream os;
os << "The number i is " << i;
strQueue.push(os.str());
return strQueue.back().data();
}
void useStr()
{
while(!strQueue.empty())
{
cout << strQueue.front() << endl;
strQueue.pop();
}
}
int main(int argc, char **argv)
{
for(int i = 0; i < 40; i++)
{
printf("Retval is: %s\n", genStr(i));
}
useStr();
return 0;
}
As the strings go out of scope when genStr() exits, I would expect the printf to just output "Retval is: ", or at the very least for the call to useStr() to give undefined results, as the memory was stomped on by the repeated allocations from the extra calls, yet both return the appropriate stored strings, without fail.
I'd like to know why this happens, but in lieu of that, I'd be happy just to know whether I can rely on this effect happening with any old object.
Thanks
As far as I'm aware, STL containers aren't meant to copy the objects which they contain
Okay, let's stop right there. STL containers do copy their contents, frequently. They copy them when they're inserted, they copy them when the container is resized either automatically or explicitly, and they copy them when the container itself is copied. Lots and lots of copying.
I'm not sure where you got the idea that STL containers don't copy their contents. The only thing that I can think of that's even close is that if you insert a pointer into an STL container, it will copy the pointer itself but not the pointed-to data.
Also, there are no references involved in your code whatsoever, so I'm puzzled as to what the title of this question refers to.
STL containers aren't meant to copy the objects which they contain
The STL is all about making copies. It will make them when you insert objects, and will sometimes make them if the underlying storage gets resized. You may get broken code if the object you are copying becomes invalidated when your function goes out of scope (for example if you add a pointer to a local variable, rather than copying the local variable).
In your case, you aren't copying a reference to a string, you're copying a string. This copied string then exists in the scope of strQueue, so the behavior you are seeing is completely valid and reliable.
Here is another misunderstanding to clear up:
In particular, string classes, which are meant to zero out the first character of their underlying storage upon destruction
C++ doesn't tend to ever do that sort of thing. It would be a hidden cost, and C++ hates hidden costs :) The string destructor won't touch the memory because once the destructor has exited, the object no longer exists. Accessing it is undefined behavior, so the C++ implementation will do whatever is fastest and least wasteful in well defined code.
All the "STL" (I hate that term) collections store copies of the objects passed to them, so the lifetime of the object in the collection is completely independent of the original object. Under normal circumstances, the collection's copy of an object will remain valid until you erase it from the collection or destroy the collection.
What goes into the container is a copy of the object and not the actual object. Similarly what you get back is also a copy. You can access these objects as long as your container is in scope.
精彩评论