副作用c ++矢量复制和删除

时间:2014-05-22 12:51:49

标签: c++ c++11 vector side-effects

我有这个问题:

void foo(vector<int> &a){
    vector<int> b;
    b.push_back(1); // in general many push backs
    a = b;
}

因为b是局部变量,所以当foo结束时它将被删除。 是否会保留插入b中的值? 我尝试过它但确实只是偶然。

感谢您的帮助。

编辑:

我认为这回答了我的问题。不是吗? http://www.cplusplus.com/reference/vector/vector/operator=/ 所以基本上a将保留c ++ 98中的值。但我无法完全理解它在c ++ 11中的作用。

3 个答案:

答案 0 :(得分:6)

a = b将调用std::vector副本分配运算符。此运算符将矢量的所有内容从b复制到a,以便之后可以安全删除b

考虑您的修改: 对于C ++ 11,这个答案也是如此。 C ++ 11只添加一个移动赋值运算符,但由于b不是r值,因此不会调用此运算符。

即使b是一个r值(例如,通过将b包装成std::move(b)),也会调用移动赋值运算符,这也没关系。它会将b的内容移动到a,因此b之后将成为空向量,也可以安全删除。

答案 1 :(得分:2)

C ++ 11中发生的事情是赋值运算符将执行复制,除非您明确告诉它使用std :: move移动。

要强制移动你可以这样做:

void foo(vector<int> &a){
    vector<int> b;
    b.push_back(1); // in general many push backs
    a = std::move(b);
}

为了实现这个目的,vector已经实现了赋值运算符来移动这样的东西:

vector<T>& vector<T>::operator =(vector<T>&& to_move) {}

使用std::move时,这会告诉编译器使用已实现移动的重载函数,否则它将在未实现移动语义的旧版本上回退到const vector<T>&

移动可能会或可能不会更快,具体取决于实现方式,但对于矢量,您可能希望内部指针从旧向量移动到新向量,从而避免复制所有包含的对象。

e.g。

vector<T>& vector<T>::operator =(vector<T>&& to_move)
{
    delete [] m_ptrs;
    m_ptrs = to_move.m_ptrs;
    m_size = to_move.m_size;
    to_move.m_ptrs = nullptr;
    to_move.m_size = 0;
    return *this;
}

这当然是一种有根据的猜测,但希望它能说明使用移动语义时会发生什么。

答案 2 :(得分:1)

如果这些值不是指针,则它们将a = b copied,因此它们将被保留(它们也会在b插入{{1}}时被复制http://www.cplusplus.com/reference/vector/vector/push_back/ })。

如果它们是,它们也会被复制,但如果它们指向局部变量,你将得到一个很好的无效指针集合。

另一方面,如果他们是动态分配内存的指针,你就不会发现任何问题。