我测试了c ++ 11移动功能,但没有生效。谁能告诉我为什么?谢谢。代码如下:
class Base {
public:
Base() { cout << "Base" << endl;}
~Base() { cout << "~Base" << endl;}
Base(const Base& base) { cout << "Copy" << endl; }
Base& operator=(const Base& base) {cout << "operator=" << endl;}
Base(Base&& base) { cout << "move" << endl;}
Base& operator=(Base&& base) { cout << "move=" << endl;}
};
Base b;
Base&& GetResult() {
return std::move(b);
}
int main() {
Base&& tmp = GetResult();
cout << &b << endl;
cout << &tmp << endl;
}
输出:
Base
0x6013a0
0x6013a0
~Base
为什么不调用move copy
和move operator=
?为什么地址是相同的?
答案 0 :(得分:7)
为了增加现有的优秀答案,我认为这里混淆的主要问题是std::move
的作用。
std::move
不会移动。
非常命名。
它只给你一个xvalue指你给它的任何东西;这个xvalue将绑定到左值引用,而左值不会。这意味着std::move
的结果可以赋予移动构造函数或移动赋值运算符。但是,它不适合你,你不在这里。
鉴于对命名的强烈批评,你肯定有另一种建议 - user2079303
这是一个很好的主题,但是the creator of C++ suggests std::rval
和one of the architects of modern C++ suggests std::rvalue_cast
(即使你真的得到了一个xvalue)。
就个人而言,我认为std::moveable
本来是个不错的中间地带。
答案 1 :(得分:3)
为什么要移动复制和移动操作符=不被调用?
我假设通过&#34;移动副本&#34;你的意思是&#34;移动构造函数&#34;。不调用移动赋值运算符,因为您从不使用赋值运算符。
没有移动(也没有副本),因为Base&&
是引用(特定的r值引用)。引用引用/指向对象 - 它们不包含对象的状态。初始化引用时,不会复制或移动任何对象。
为什么地址是一样的?
当address-of运算符应用于引用时,您将获得引用对象的地址。
答案 2 :(得分:2)
让我们忽略移动语义一分钟,只考虑熟悉的C ++ 98拷贝构造函数。鉴于以下代码,您期望得到什么输出?
class Base {
public:
Base() { cout << "Base" << endl;}
~Base() { cout << "~Base" << endl;}
Base(const Base& base) { cout << "Copy" << endl; }
Base& operator=(const Base& base) {cout << "operator=" << endl;}
};
Base b;
Base& GetResult() {
return b;
}
int main() {
Base& tmp = GetResult();
cout << &b << endl;
cout << &tmp << endl;
}
当然,您需要调用Base
默认构造函数,然后打印两次b
地址,然后是Base
析构函数。原因是因为您只构建了一个Base
实例,并且从不复制它 - 您只是使用引用。
所以这是你的榜样。您使用右值引用而不是左值引用,但重点是相同的 - 只有一个Base
变量,并且不会发生任何复制或移动。如果你想见证移动语义,你可以尝试这样的事情:
Base getBase() {
return Base{};
}
int main() {
Base tmp = getBase();
Base other = std::move(tmp);
}
(移出getBase()
可能会被编译器优化掉,但你仍然应该看到第二个。)