自动变量初始化和 copy/move 构造函数
Automatic variable initialization and copy/move constructor
我有一个片段:
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.
为什么我认为毕竟会有模板类型推导和直接初始化?有人可以解释一下在这种情况下自动变量初始化是如何工作的吗?
Why I thought there will be a template type deduction
auto
使用模板参数推导规则推导变量的类型。在这种情况下,类型将被推断为 MyCass2
.
and a direct initialization after all?
a
不是 direct-initialized, because you used copy-initialization - 请参阅标记为 (1) 的语法。
how the automatic variable initialization work in this case?
a
是从 =
右侧的临时文件复制初始化的。但是,由于该类型既不可复制也不可移动,因此不允许进行复制初始化。
But I [defined] the move/copy constructors and neither of them was called, how is that?
默认构造函数用于初始化临时对象。复制初始化中move构造函数的调用允许为elided.
I was sure that this auto var=initializer is kind of a syntax overloading. Like with copy initialization T var=initializer, where instead of operator= a copy constructor is called.
嗯,事实并非如此。这里,auto
用于且仅用于推导类型。一旦推断出类型,表达式就完全等同于
MyCass2 a = MyCass2();
auto a = MyCass2();
使用copy/move初始化。现在,由于您声明了移动构造函数(是的,已删除的函数仍然是已声明的函数),编译器将尝试使用它来将临时对象移动到 a
中,因为它是最佳匹配。当它这样做时,它会尝试使用已删除的移动构造函数。尝试使用已删除的函数格式不正确,编译器会生成错误。
如果你想让上面的代码工作,你需要定义复制或移动构造函数。请注意,在
这样的情况下
auto a = some_named_myclass2_object;
需要定义复制构造函数,因为 some_named_myclass2_object
是一个左值,没有 std::move
就不能移动
我有一个片段:
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.
为什么我认为毕竟会有模板类型推导和直接初始化?有人可以解释一下在这种情况下自动变量初始化是如何工作的吗?
Why I thought there will be a template type deduction
auto
使用模板参数推导规则推导变量的类型。在这种情况下,类型将被推断为 MyCass2
.
and a direct initialization after all?
a
不是 direct-initialized, because you used copy-initialization - 请参阅标记为 (1) 的语法。
how the automatic variable initialization work in this case?
a
是从 =
右侧的临时文件复制初始化的。但是,由于该类型既不可复制也不可移动,因此不允许进行复制初始化。
But I [defined] the move/copy constructors and neither of them was called, how is that?
默认构造函数用于初始化临时对象。复制初始化中move构造函数的调用允许为elided.
I was sure that this auto var=initializer is kind of a syntax overloading. Like with copy initialization T var=initializer, where instead of operator= a copy constructor is called.
嗯,事实并非如此。这里,auto
用于且仅用于推导类型。一旦推断出类型,表达式就完全等同于
MyCass2 a = MyCass2();
auto a = MyCass2();
使用copy/move初始化。现在,由于您声明了移动构造函数(是的,已删除的函数仍然是已声明的函数),编译器将尝试使用它来将临时对象移动到 a
中,因为它是最佳匹配。当它这样做时,它会尝试使用已删除的移动构造函数。尝试使用已删除的函数格式不正确,编译器会生成错误。
如果你想让上面的代码工作,你需要定义复制或移动构造函数。请注意,在
这样的情况下auto a = some_named_myclass2_object;
需要定义复制构造函数,因为 some_named_myclass2_object
是一个左值,没有 std::move