我的问题很简单。当我使用STL容器时,它们是否复制了我存储的值(通过使用复制构造函数)?如果我给它们数组(char *)而不是字符串实例怎么办?他们的表现如何?是否保证信息将存储在堆而不是系统堆栈中?
感谢您的回答。
答案 0 :(得分:7)
STL容器中的值按值存储。如果你有这样的矢量:
class BigObject
{
...
};
vector<BigObject> myObjs;
myObjs.push_back(obj1);
myObjs.push_back(obj2);
...
向量将复制您正在推送的对象。同样在向量的情况下,它可能在以后必须重新分配底层内存时创建新副本,因此请记住这一点。
当你有一个指针向量,如vector<char*>
时,同样的事情也是如此 - 但这里的区别在于复制的值是指针,而不是它指向的字符串。所以如果你有:
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;
...向量将获得指针的副本。它获得的指针将具有相同的值(0x1234),并且由于您在推入指针后delete
指向该指针,因此您的向量包含一个野指针,并且您的代码最终会崩溃(希望比以后更快)。
顺便说一句,如果不使用char * s,你可以避免使用字符串:
typedef vector<string> strings;
strings myStrings;
myStrings.push_back("Hello, buffer");
答案 1 :(得分:5)
他们复制价值。大多数(所有?)容器都要求定义复制构造函数和赋值运算符。
如果你给他们一个char*
,他们会复制指针,而不是指向的值。那么你有责任确保字符串本身在它仍在使用时不会被销毁,并在不再需要时被销毁。
答案 2 :(得分:3)
他们总是制作副本。如果您创建了vector<char *>
,那么它会复制您推入的char*
。但是,它不会复制指针指向的字符串。如果该字符串是动态分配的,那么您可能会有泄漏,这就是vector<string>
通常无限优先的原因。
答案 3 :(得分:1)
当你放入它们时,它们总是复制。如果你给它们一个指针,那么他们复制指针。指针指向的数据不受影响。注意,不建议将原始指针放入stl容器中,因为很容易丢失它们并泄漏内存。 STL容器并非旨在帮助您使用原始指针。如果你想在STL容器中使用指针,可以考虑使用boost中的shared_ptr来包装它们。
答案 4 :(得分:1)
您已经得到了许多答案,指出当您将数据放入容器时,它会按值存放,因此容器中的内容是原始数据的副本。
此规则有一种例外:std::list
有一个splice
成员,允许您将一个列表的一部分(或全部)插入到另一个列表中。在这种情况下,数据通常是移动而不是复制 - 至少通常,拼接是通过操纵指针完成的,因此一个列表中的节点被移植到另一个列表中。
例外情况是两个列表使用不同的分配器类型。在这种情况下,我认为splice必须分配新节点,复制数据,然后释放旧节点。然后,这是一个相当模糊的角落案例 - 大多数人从不实现自己的分配器类型。
答案 5 :(得分:0)
此外,如果您不希望复制整个对象的开销并且不喜欢与使用指针相关联的头痛,则可以在向量中使用boost :: shared_ptr以确保仅动态分配的内存将被释放当它不再被引用时。