【发布时间】:2018-07-13 16:42:45
【问题描述】:
我正在尝试理解 c++11 移动语义,并创建了以下沙盒项目:
main.cpp
#include "my-class.h"
#include <iostream>
MyOtherClass getRValue(void)
{
MyOtherClass retVal;
std::cout << "Address of getRValue local var is " << &retVal << std::endl;
std::cout << "Returning from getRValue...\n";
return retVal;
}
int main()
{
MyClass bar(getRValue());
std::cout << "Address of bar member is " << &(bar.getObjRef()) << std::endl;
return 0;
}
my-class.h
#ifndef MY_CLASS_H_INCLUDED
#define MY_CLASS_H_INCLUDED
#include <iostream>
class MyOtherClass
{
private:
int somePOD;
char someOtherPOD;
public:
MyOtherClass(void);
MyOtherClass(MyOtherClass const& argOther);
MyOtherClass(MyOtherClass&& argOther);
};
class MyClass
{
private:
MyOtherClass obj;
public:
MyClass(MyOtherClass&& arg);
MyOtherClass& getObjRef(void);
};
#endif // MY_CLASS_H_INCLUDED
my-class.cpp
#include "my-class.h"
// Class MyOtherClass
MyOtherClass::MyOtherClass(void)
: somePOD(42), someOtherPOD('x')
{
std::cout << "MyOtherClass c'tor called.\n";
}
MyOtherClass::MyOtherClass(MyOtherClass const& argOther)
{
std::cout << "MyOtherClass copy c'tor called.\n";
}
MyOtherClass::MyOtherClass(MyOtherClass&& argOther)
{
std::cout << "MyOtherClass move c'tor called.\n";
}
// Class MyClass
MyClass::MyClass(MyOtherClass&& arg)
: obj(std::move(arg))
{
std::cout << "MyClass c'tor called.\n";
}
MyOtherClass& MyClass::getObjRef(void)
{
return this->obj;
}
这段代码打印输出:
MyOtherClass c'tor called.
Address of getRValue local var is 0x7fff882a2db8
Returning from getRValue...
MyOtherClass move c'tor called.
MyClass c'tor called.
Address of bar member is 0x7fff882a2db0
我的问题是:为什么是本地变量的地址。和酒吧会员不同?这两者是否相同不是移动语义的全部意义吗?还是我只是在我的示例中做错了什么?
【问题讨论】:
-
“这不是移动语义的重点吗”?不,不是。移动语义将一个对象的内容移动到另一个对象中。它不会以某种方式神奇地将两个不同的对象合二为一。这些是并且将永远是两个不同的对象。不同的对象总是有不同的地址。在您的示例中,没有真正的 movable 内容,这意味着您示例中的移动语义始终与复制语义相同:所有内容都只是简单地复制。
-
好吧,是什么让
std::vector成为可移动内容,而int不是?数据的内容是否应该以某种方式驻留在堆中?只有当我在MyOtherClass中动态分配数组成员并在移动构造函数中复制指针而不是迭代深拷贝时,这段代码才有意义? -
是的,你的想法是对的。事实上,在典型的实现中
std::vector存储了一个指向其元素数组的 指针 - 这就是使std::vector可移动的原因。为了将一个向量的内容移动到另一个向量中,您只需要将指针复制到接收者(并重置源)。这就是移动语义真正起作用的地方:您必须将内容间接存储为“指针”或“句柄”。但是当您直接/立即存储内容(如您的示例中)时,移动语义“不起作用”:它被简化为普通的复制语义。 -
@corsel 由 devolpers 显式编码
-
@corsel:这取决于实现细节。如果
std::vector通过原始指针 引用它的数据,那么它必须显式地实现它的移动语义。如果它改用一些智能指针,那么智能指针可能能够自己正确处理它。在任何情况下,它都会归结为原始指针和手动实现。
标签: c++ c++11 move-semantics rvalue-reference