5

我最近开始使用c++,我选择学习c++11特性。但是 c++ 代码的运行方式有时并不那么具体。

下面是我的代码。在decltype(std::move(sample)) sample2 = std::move(sample);我不确定为什么这条线不调用移动构造函数的部分。你能解释一下为什么吗?

#include <iostream>

class AAA
{
   public:
      AAA() { std::cout << "default constructor" << std::endl; }
      AAA(const AAA& cs) { std::cout << "copy constructor" << std::endl; }
      AAA(AAA&& cs) { std::cout << "move constructor" << std::endl; }
      ~AAA() { std::cout << "destructor" << std::endl; }
};

int main(int argc, char* args[])
{
    AAA sample;
// ((right here))
    decltype(std::move(sample)) sample2 = std::move(sample); 
    return 0;
}

它是在 [ubuntu 16.04 LTS] 和 [gcc 5.4.0] 上编译的

原始代码:https ://ide.geeksforgeeks.org/tALvLuSNbN

4

2 回答 2

6

您的代码段扩展为

AAA&& sample2 = std::move(sample);

它将一个右值( 的结果std::move(sample))绑定到一个右值引用(sample2)。没有构造新对象,因此没有调用这样的构造函数。

于 2018-07-16T15:21:30.417 回答
6

该函数std::move<T>返回 a T &&,因此std::move(sample)它返回AAA &&。这是一个右值引用,其行为很像左值引用(一种类型AAA &可能是左值引用),因为它们都是已经存在的对象的别名。

重要的是要理解它std::move本身不会导致任何东西被移动。它只是返回一个对它给出的参数的右值引用。例如std::move(foo);,独自一人绝对什么都不做。只有当结果用于初始化或分配给一个对象时,它才会变得有用。

例如auto bar = std::move(foo);,将返回一个右值引用foo并将该引用用于 callbar的构造函数。

要回答这个问题,因为std::move(sample)返回 a AAA &&,所以有问题的行与 相同AAA && sample2 = std::move(sample);。行为实际上与AAA & sample2 = sample;. 在这两种情况下,您都在初始化对现有对象的引用,并且不需要构造新对象。

如果你的目标是搬进sample一个新AAA的,正确的路线会auto sample2 = std::move(sample);像你一样用sample3。虽然要注意这条线sample3是从一个已经移动的位置移动的sample

于 2018-07-16T15:37:41.507 回答