C++ 11:使用std :: move()的'decltype类实例声明'不会调用'move constructor'.为什么?

Kis*_*Yoo 5 c++ decltype move-semantics c++11 stdmove

我最近开始使用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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

lub*_*bgr 6

您的代码段扩展为

AAA&& sample2 = std::move(sample);
Run Code Online (Sandbox Code Playgroud)

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


Fra*_*eux 6

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

重要的是要理解,std::move这本身并不会导致任何事情被移动.它只是返回一个rvalue引用给它给出的参数.例如,std::move(foo);单独做什么都没有.仅当结果用于初始化或分配给对象时才有用.

例如,auto bar = std::move(foo);将返回一个rvalue引用foo并使用该引用来调用其bar构造函数.

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

如果你的目标是sample进入一个新的AAA,那么正确的线auto sample2 = std::move(sample);就像你一样sample3.虽然要注意这条线sample3正在从一个已经移动的线上移开sample.