我有这个问题:
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中的作用。
答案 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/ })。
如果它们是,它们也会被复制,但如果它们指向局部变量,你将得到一个很好的无效指针集合。
另一方面,如果他们是动态分配内存的指针,你就不会发现任何问题。