std :: vector是否使用push_back复制对象?

ben*_*aug 157 c++ stl stdvector

经过对valgrind的大量调查后,我得出结论,std :: vector制作了你想要push_back的对象的副本.

这是真的吗?没有副本,向量不能保留对象的引用或指针?

谢谢

Ale*_*ler 174

是的,std::vector<T>::push_back()创建参数的副本并将其存储在向量中.如果要存储指向矢量中对象的指针,请创建一个std::vector<whatever*>而不是std::vector<whatever>.

但是,您需要确保指针引用的对象保持有效,而向量包含对它们的引用(智能指针利用RAII习惯用法解决问题).

  • 从C++ 11开始,如果参数是右值引用,`push_back`将执行移动而不是副本.(可以使用`std :: move()`将对象转换为右值引用.) (22认同)
  • +1表示需要智能指针 (11认同)
  • @tuple_cat你的评论应该说"如果参数是一个右值".(如果参数是声明为rvalue引用的实体的名称,那么参数实际上是一个左值并且不会被移动) - 检查我的编辑到"Karl Nicoll"的答案,最初犯了这个错误 (2认同)

Geo*_*che 34

是的,std::vector存储副本.应该如何vector知道物体的预期寿命是多少?

如果你想传输或共享对象的所有权使用指针,可能是智能指针shared_ptr(在BoostTR1中找到)以简化资源管理.

  • 学会使用shared_ptr - 他们完全按照你的意愿行事.我最喜欢的成语是typedef boost :: shared_ptr <Foo> FooPtr; 然后制作FooPtrs的容器 (3认同)
  • @ pm100 - 你知道`boost :: ptr_vector`吗? (3认同)
  • 我也喜欢使用`class Foo {typedef boost :: shared_ptr <Foo> ptr; ``只写`Foo :: ptr`. (2认同)
  • @ pm100 - `shared_ptr`并不完全是火,忘了.请参阅http://stackoverflow.com/questions/327573/和http://stackoverflow.com/questions/701456/ (2认同)
  • 如果您拥有共享所有权,shared_ptr很好,但它通常被过度使用.当所有权明确时,unique_ptr或boost scoped_ptr会更有意义. (2认同)

Kar*_*oll 27

从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");
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用各种智能指针来获得大致相同的效果:

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"));
Run Code Online (Sandbox Code Playgroud)

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.
Run Code Online (Sandbox Code Playgroud)

  • 注意`std :: make_unique`仅在C ++ 14及更高版本中可用(令人讨厌)。如果要编译这些示例,请确保告诉编译器相应地设置其标准一致性。 (2认同)
  • @ user465139`make_unique`可以很容易地在C++ 11中实现,所以对于那些坚持使用C++ 11编译器的人来说,这只是一个小麻烦 (2认同)

Ree*_*sey 15

std :: vector总是复制存储在向量中的任何内容.

如果你保留一个指针向量,那么它将复制指针,但不是指针所指向的实例.如果您正在处理大型对象,则可以(并且可能应该)始终使用指针向量.通常,使用适当类型的智能指针向量有利于安全目的,因为处理对象的生命周期和内存管理可能会很棘手.

  • 它不取决于类型.它总是制作副本.如果它的指针是指针的副本 (3认同)
  • 是的,它总是在复制 - 然而,OP所指的“对象”很可能是一个类或结构,所以我指的是它是否复制“对象”取决于定义。不过措辞不好。 (2认同)