似乎我无法完全理解移动语义:我想从外部函数填充std::vector
(类的成员)。目前,我有类似的东西:
void fillVector(MyClass & myclass) {
std::vector<int> vec;
/* Filling vec */
// ...
myclass.setVector(vec);
}
class MyClass {
public:
setVector(const std::vector<int> & v) { v_ = v;}
private:
std::vector<int> v_;
};
int main() {
MyClass myclass;
fillVector(myclass);
/* Use myclass.v_ somehow */.
}
我有很长一段时间的代码,它运行正常。现在,我无法理解它是如何工作的,因为我将对一个将被销毁的向量的引用作为参考。我的问题是:
fillVector
和MyClass::setVector()
的最佳方式是什么?我认为可以用移动语义完成,但我无法弄清楚如何。谢谢!
答案 0 :(得分:6)
为什么代码有效:
vec
的范围是fillVector
的主体。在整个范围内,vec
完全有效。这包括致电setVector
。 v
(setVector
的参数)是绑定到vec
的引用。 setVector
的正文将向量vec
(作为v
访问)的内容复制到v_
。这是一个实际的数据副本,没有参考分配。仅在setVector
结束后fillVector
结束,此时vec
被销毁。但它已被复制,所以一切都很好。
如何使用移动语义:
您可以提供setVector
的额外重载,它将采用右值引用:
class MyClass {
public:
// ...
void setVector(std::vector<int> &&v) { v_ = std::move(v); }
// ...
};
然后,将 vec
移至setVector
:
void fillVector(MyClass & myclass) {
std::vector<int> vec;
/* Filling vec */
// ...
myclass.setVector(std::move(vec));
}
这将调用rvalue重载而不是lvalue重载,数据将被移动,而不是被复制。
但是,也许更好的界面是重构fillVector
,以便它按值返回向量,自动使用移动语义:
std::vector<int> fillVector() {
std::vector<int> vec;
/* Filling vec */
// ...
return vec; // Note that a move automatically happens here, or even NRVO
}
int main() {
MyClass myclass;
myclass.setVector(fillVector());
/* Use myclass.v_ somehow */.
}
答案 1 :(得分:1)
vector :: operator =指定内容,并且不会链接到现有项目。当你执行v_ = v时,v_获取v中所有内容的新副本。一旦v被销毁,v_中的项目仍然存在。
测试此功能并查看此操作的简单方法是更改v_ [i]中的某个项目,然后查看打印出v [i]和v_ [i]。他们将是不同的。
我没有看到你的setVector和fillVector的实现有什么问题。你有什么特别想要实现的目标吗?