C++ std::vector 是否使用 push_back 复制对象?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2275076/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is std::vector copying the objects with a push_back?
提问by benlaug
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.
在对 valgrind 进行了大量调查之后,我得出的结论是 std::vector 制作了您想要 push_back 的对象的副本。
Is that really true ? A vector cannot keep a reference or a pointer of an object without a copy ?!
这是真的吗?向量不能在没有副本的情况下保留对象的引用或指针?!
Thanks
谢谢
回答by Alexander Gessler
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>
.
是的,std::vector<T>::push_back()
创建参数的副本并将其存储在向量中。如果要在向量中存储指向对象的指针,请创建一个std::vector<whatever*>
而不是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).
但是,您需要确保指针引用的对象在向量持有对它们的引用时保持有效(使用 RAII 习语的智能指针解决了该问题)。
回答by Georg Fritzsche
Yes, std::vector
stores copies. How should vector
know what the expected life-times of your objects are?
是的,std::vector
存储副本。如何vector
知道对象的预期寿命是多少?
If you want to transfer or share ownership of the objects use pointers, possibly smart pointers like shared_ptr
(found in Boostor TR1) to ease resource management.
如果您想转移或共享对象的所有权,请使用指针,可能是智能指针shared_ptr
(在Boost或TR1 中找到)以简化资源管理。
回答by Karl Nicoll
From C++11 onwards, all the standard containers (std::vector
, std::map
, etc) support move semantics, meaning that you can now pass rvalues to standard containers and avoid a copy:
从 C++11 开始,所有标准容器(std::vector
、std::map
等)都支持移动语义,这意味着您现在可以将右值传递给标准容器并避免复制:
// 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");
Alternatively you can use various smart pointers to get mostly the same effect:
或者,您可以使用各种智能指针来获得大致相同的效果:
std::unique_ptr
example
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
example
std::shared_ptr
例子
std::vector<std::shared_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.
回答by Reed Copsey
std::vector always makes a copy of whatever is being stored in the vector.
std::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.
如果您保留一个指针向量,那么它将创建指针的副本,而不是指针指向的实例。如果您正在处理大型对象,您可以(并且可能应该)始终使用指针向量。通常,使用适当类型的智能指针向量有利于安全目的,因为否则处理对象生命周期和内存管理可能会很棘手。
回答by Liz Albin
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.
std::vector 不仅会复制您所推回的任何内容,而且集合的定义指出它将这样做,并且您不能在向量中使用没有正确复制语义的对象。因此,例如,您不在向量中使用 auto_ptr。
回答by LemonPi
Relevant in C++11 is the emplace
family of member functions, which allow you to transfer ownership of objects by moving them into containers.
C++11 中相关的是emplace
成员函数系列,它允许您通过将对象移动到容器中来转移对象的所有权。
The idiom of usage would look like
使用习惯用法看起来像
std::vector<Object> objs;
Object l_value_obj { /* initialize */ };
// use object here...
objs.emplace_back(std::move(l_value_obj));
The move for the lvalue object is important as otherwise it would be forwarded as a reference or const reference and the move constructor would not be called.
左值对象的移动很重要,否则它将作为引用或常量引用转发,并且不会调用移动构造函数。
回答by rahmivolkan
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.
如果你不想要副本;那么最好的方法是使用指针向量(或用于同一目标的其他结构)。如果你想要副本;直接使用push_back()。你别无选择。
回答by NexusSquared
Why did it take a lot of valgrind investigation to find this out! Just prove it to yourself with some simple code e.g.
为什么要经过大量的 valgrind 调查才能发现这一点!只需用一些简单的代码证明给自己,例如
std::vector<std::string> vec;
{
std::string obj("hello world");
vec.push_pack(obj);
}
std::cout << vec[0] << std::endl;
If "hello world" is printed, the object must have been copied
如果打印“hello world”,则该对象必须已被复制