c ++ 11移动没有效果?

时间:2017-04-20 15:23:52

标签: c++ linux c++11 move

我测试了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 copymove operator=?为什么地址是相同的?

3 个答案:

答案 0 :(得分:7)

为了增加现有的优秀答案,我认为这里混淆的主要问题是std::move的作用。

std::move不会移动。

非常命名。

它只给你一个xvalue指你给它的任何东西;这个xvalue将绑定到左值引用,而左值不会。这意味着std::move 的结果可以赋予移动构造函数或移动赋值运算符。但是,它不适合你,你不在这里。

  

鉴于对命名的强烈批评,你肯定有另一种建议    - user2079303

这是一个很好的主题,但是the creator of C++ suggests std::rvalone 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()可能会被编译器优化掉,但你仍然应该看到第二个。)