自动变量初始化和复制/移动构造函数

时间:2016-05-11 12:03:04

标签: c++ c++11 auto

我有一个片段:

struct MyCass2 {
  MyCass2() {}

  MyCass2(MyCass2 const&) = delete;

  MyCass2(MyCass2&&) = delete;
};

int
main() {
  auto a = MyCass2();
}

这导致

main.cpp:43:8: error: call to deleted constructor of 'MyCass2'
  auto a = MyCass2();
       ^   ~~~~~~~~~
main.cpp:38:3: note: 'MyCass2' has been explicitly marked deleted here
  MyCass2(MyCass2&&) = delete;
  ^
1 error generated.

为什么我认为会有模板类型演绎和直接初始化?有人可以解释一下自动变量初始化在这种情况下是如何工作的吗?

2 个答案:

答案 0 :(得分:5)

  

为什么我认为会有模板类型扣除

auto使用模板参数推导的规则来推导变量的类型。在这种情况下,类型将推断为MyCass2

  毕竟

和直接初始化?

a不是direct-initialized,因为您使用了copy-initialization - 请参阅标记为(1)的语法。

  

在这种情况下自动变量初始化如何工作?

a是从=右侧的临时文件进行初始化的。但是,由于该类型既不可复制也不可移动,因此不允许复制初始化。

  

但是我[定义]移动/复制构造函数并且它们都没有被调用,那是怎么回事?

默认构造函数用于初始化临时。复制初始化中对move构造函数的调用允许为elided

  

我确信这个auto var = initializer是一种语法重载。与复制初始化T var = initializer一样,而不是operator =调用复制构造函数。

嗯,事实并非如此。这里,auto用于,仅用于推断类型。推断出类型后,表达式完全等同于

MyCass2 a = MyCass2();

答案 1 :(得分:3)

auto a = MyCass2();

使用复制/移动初始化。既然你已经声明了一个移动构造函数(是的,删除的函数仍然是声明的函数),编译器将尝试使用它将临时移动到a,因为它是最佳匹配。当它尝试使用已删除的移动构造函数时,它会这样做。尝试使用已删除的函数生成错误,编译器会生成错误。

如果要允许上述代码工作,则需要定义复制或移动构造函数。请注意,例如

auto a = some_named_myclass2_object;

复制构造函数需要定义为some_named_myclass2_object是左值,如果没有std::move

,则无法移动