我有一个片段:
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.
为什么我认为会有模板类型演绎和直接初始化?有人可以解释一下自动变量初始化在这种情况下是如何工作的吗?
答案 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