std::move
不会做任何东西的对象,它所做的就是通过引用转发它的参数,并使它像一个右值绑定。换句话说,它只是返回一个匿名右值引用的对象,认为:
template<class T>
T&& std::move(T&& arg)
{
return static_cast<T&&>(arg);
}
(这是比这稍微复杂一些,但我的目标是为了便于阅读)
什么实际发生在这里出口是:
CBuffer rv(std::move(out));
return rv;
这是调用CBuffer的移动构造函数。
很多人陷入思维std :: move的陷阱实际上执行的举动,恕我直言,它的名字很差。
如果你写的代码是这样的:
CBuffer BufferReader::read(const int size)
{
CBuffer out(read_raw(), size, true);
skip(size);
return out;
}
那么大多数编译器应该能够执行“返回值优化”;也就是说,他们会悄悄假装你做了等同于:
void BufferReader::read(const int size, CBuffer* out)
{
new (out) CBuffer(read_raw(), size, true); //in-place new
skip(size);
}
,并在您有
CBuffer x = reader.read(size);
调用网站,他们会假装你正在写
CBuffer* x = (CBuffer*)alloca(sizeof(CBuffer));
reader.read(size, &x);
再次简化一下,上面的代码是在栈上分配一个CBuffer,然后在被调用者内部初始化它。这节省了在回报中执行副本。
理论上返回使得副本返回,所以原理在理论上被破坏。给定一个正确定义的类,这不是一个问题。 – chris
除非[RVO](http://en.wikipedia.org/wiki/Return_value_optimization)进来,它应该在复制/移动后调用析构函数。 –
为什么不展示CBuffer类的基础知识?不是每个函数,而是这里使用的构造函数,复制构造函数,析构函数和关键数据成员?您可能会得到有关如何改进复制构造函数以实现此功能的有用建议。 – NicholasM