【发布时间】:2014-03-18 03:50:16
【问题描述】:
我试图让我清楚移动语义。我正在关注 Bjarne Stroustrup 第 4 版的示例,我真的迷路了。
他说当很多元素(在类向量中)时,对象的副本可能会很昂贵,因此移动语义是解决方案。
想一想:
向量结果 = vector1 + vector2 + vector3;
顺序可能是错误的,但它会(vector2 + vector3)生成部分结果result1,result1 + vector1,生成结果;
我重载了operator+:
Vector operator+(const Vector &a,const Vector &b)
{
if(a.size()!=b.size()) {
throw length_error{"Length of vectors must match for summing"};
}
Vector result(a.size());
cout << "Intermediate result for sum created" << endl;
for(long unsigned int i=0; i<result.size();i++){
result[i] = a[i] + b[i];
}
return result;
}
我还创建了一个移动构造函数:
Vector::Vector(Vector&& orig) noexcept
:elem{orig.elem},
sz{orig.sz}
{
cout << "Move constructor called" << endl;
orig.elem = nullptr; // We own the array now
orig.sz = 0;
}
因此不执行复制操作。但是有些事情我不明白。一个只与 c++ 相关,另一个与 c++11 相关。
首先:
如你所见,当 operator+ 退出时,Vector 结果应该被销毁。但不是在内容被复制到另一个向量实例之后。我称之为部分结果1。
这永远不会发生,程序的输出是这样的:
- 创建了新的类向量
- 已创建总和的中间结果
- 已创建新类向量 转到结果
- 已创建总和的中间结果
- 类向量被破坏
但是直到程序结束我才看到第二个部分结果被破坏。我也没有看到任何复制操作(我已经完成了 operator= 和复制构造函数)。
所以我不明白。如果变量 Vector 结果的范围在 operator+ 内,则必须将内容复制到另一个变量。那还没有完成。似乎总和的最后一个结果只是分配给总和的向量结果。
第二:
不执行任何移动操作。我无法让移动语义在这里工作。我查看了http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52745 并应用了那里的内容,但无论如何都没有移动操作。
每个结果都是正确的。
很明显,我做错了什么。
您可以从这里获取整个代码(使用 autotools config + eclipse):
http://static.level2crm.com/cx11-learn-20140218.tar.bz2
谁能解释一下这里发生了什么?
最好的问候,
【问题讨论】:
-
比搬家更便宜的是(N)RVO,这就是你所看到的。
-
如果您使用的是 g++,请尝试设置 -fno-elide-constructors。 (正如 jrok 所说,您看到的应该是 NRVO 的结果)