是std ::向量复制与push_back对象?
经过与valgrind的很多调查后,我已经得出结论,std :: vector做了一个你想push_back对象的副本。
这是真的吗? 一个向量不能保留一个对象的引用或指针,而没有副本?
谢谢
是的, std::vector<T>::push_back()
创build参数的一个副本并将其存储在向量中。 如果你想存储指向你的向量中的对象的指针,创build一个std::vector<whatever*>
而不是std::vector<whatever>
。
但是,您需要确保指针所引用的对象保持有效,而向量持有对它们的引用(使用RAII成语的智能指针可以解决问题)。
是的, std::vector
存储副本。 vector
怎么知道你的物体的预期寿命是多less?
如果您想传输或共享对象使用指针的所有权,可能会使用智能指针(如Boost或TR1中的 shared_ptr
)来简化资源pipe理。
std :: vector总是复制一个存储在vector中的东西。
如果你保存了一个指针向量,那么它将会创build一个指针的副本,而不是指针指向的实例。 如果你正在处理大对象,你可以(也可能应该)总是使用一个指针向量。 通常,使用适当types的智能指针向量对于安全目的是有利的,因为否则处理对象生存期和内存pipe理可能是棘手的。
从C ++ 11开始,所有的标准容器( std::vector
, std::map
等)都支持移动语义,这意味着你现在可以将rvalues传递给标准容器并避免复制:
// Example object class. class object { private: int m_val1; std::string m_val2; public: // Constructor for object class. object(int val1, std::string &&val2) : m_val1(val1), m_val2(std::move(val2)) { } }; std::vector<object> myList; // #1 Copy into the vector. object foo1(1, "foo"); myList.push_back(foo1); // #2 Move into the vector (no copy). object foo2(1024, "bar"); myList.push_back(std::move(foo2)); // #3 Move temporary into vector (no copy). myList.push_back(object(453, "baz")); // #4 Create instance of object directly inside the vector (no copy, no move). myList.emplace_back(453, "qux");
或者,您可以使用各种智能指针获得大致相同的效果:
std::unique_ptr
例子
std::vector<std::unique_ptr<object>> myPtrList; // #5a unique_ptr can only ever be moved. auto pFoo = std::make_unique<object>(1, "foo"); myPtrList.push_back(std::move(pFoo)); // #5b unique_ptr can only ever be moved. myPtrList.push_back(std::make_unique<object>(1, "foo"));
std::shared_ptr
示例
std::vector<std::unique_ptr<object>> objectPtrList2; // #6 shared_ptr can be used to retain a copy of the pointer and update both the vector // value and the local copy simultaneously. auto pFooShared = std::make_shared<object>(1, "foo"); objectPtrList2.push_back(pFooShared); // Pointer to object stored in the vector, but pFooShared is still valid.
std :: vector不仅可以制作任何推回的副本,而且集合的定义表明它将这样做,并且不能在向量中使用没有正确复制语义的对象。 所以,例如,你不要在向量中使用auto_ptr。
在C ++ 11中相关的是emplace
系列的成员函数,它允许你通过将对象的所有权移动到容器中来转移对象的所有权。
用法的习惯看起来像
std::vector<Object> objs; Object l_value_obj { /* initialize */ }; // use object here... objs.emplace_back(std::move(l_value_obj));
左值对象的移动很重要,否则它将作为引用或常量引用转发,移动构造函数将不会被调用。
如果你不想要的副本; 那么最好的方法就是使用一个指针向量(或者为同一个目标服务的另一个结构)。 如果你想要的副本; 直接使用push_back()。 你没有其他select。
为什么需要大量的valgrind调查才能发现这一点! 只需用一些简单的代码来certificate自己
std::vector<std::string> vec; { std::string obj("hello world"); vec.push_pack(obj); } std::cout << vec[0] << std::endl;
如果打印“hello world”,则必须复制对象