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

时间:2010-02-16 17:54:45

标签: c++ stl stdvector

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

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

由于

8 个答案:

答案 0 :(得分:160)

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

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

答案 1 :(得分:33)

是的,std::vector存储副本。 vector应该如何知道对象的预期生命周期是什么?

如果要传输或共享对象的所有权,请使用指针,可能是shared_ptr(在Boost TR1 中找到)等智能指针,以简化资源管理。 / p>

答案 2 :(得分:24)

从C ++ 11开始,所有标准容器(std::vectorstd::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::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.

答案 3 :(得分:15)

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

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

答案 4 :(得分:3)

std :: vector不仅会复制你正在推回的任何内容,而且集合的定义表明它会这样做,并且你不能在向量中使用没有正确复制语义的对象。因此,例如,您不在向量中使用auto_ptr。

答案 5 :(得分:2)

C ++ 11中的相关内容是emplace成员函数系列,它允许您通过将对象移动到容器中来转移对象的所有权。

使用的习语看起来像

std::vector<Object> objs;

Object l_value_obj { /* initialize */ };
// use object here...

objs.emplace_back(std::move(l_value_obj));

对于左值对象的移动很重要,否则它将作为引用或const引用转发,并且不会调用移动构造函数。

答案 6 :(得分:0)

如果你不想要副本;那么最好的方法是使用指针向量(或用于同一目标的其他结构)。 如果你想要副本;直接使用push_back()。 你别无选择。

答案 7 :(得分:0)

为什么需要进行大量的valgrind调查才能找到答案! 只需用一些简单的代码向自己证明,例如。

std::vector<std::string> vec;

{
      std::string obj("hello world");
      vec.push_pack(obj);
}

std::cout << vec[0] << std::endl;  

如果&#34;你好世界&#34;打印时,必须复制对象