我有以下代码以及下面的输出。我似乎无法理解为什么一组花括号初始化会导致调用移动构造函数,而另一组则导致调用复制构造函数。我已经将其缩小到直接列表初始化与复制列表初始化之间,详见https://en.cppreference.com/w/cpp/language/list_initialization。我只是无法确定我的代码属于哪种情况。提前致谢。
这将导致:
#include <cstdint>
#include <iostream>
using namespace std;
struct Foo {
Foo() {
cout << "create foo\n";
}
~Foo() {
cout << "delete foo\n";
}
Foo(const Foo& f) {
cout << "copy foo\n";
}
Foo(Foo&& f) noexcept {
cout << "move foo\n";
}
Foo& operator=(const Foo& f) = delete;
Foo& operator=(Foo&& f) = delete;
};
int32_t main() {
pair<uint32_t, Foo> f1{0, Foo{}}; // Calls move ctor
cout << "------------------------\n";
pair<uint32_t, Foo> f2{0, {}}; // Calls copy ctor
cout << "------------------------\n";
return 0;
}
这将导致:
create foo
move foo
delete foo
------------------------
create foo
copy foo
delete foo
------------------------
delete foo
delete foo
explicit
,即如果它们需要调用的任何构造函数是explicit
,则它们也是explicit
。它们在之前的版本中是无条件的explicit
,而改变为有条件的explicit
是作为一个缺陷报告来实现的。 - L. F.Foo{}
而不是{}
。 - treeFoo{}
传递给参数也可以正常工作。 - L. F.{}
初始化Foo
时,编译器无法确定完美转发std::pair
构造函数的类型,因为类型缺失,因此下一个最佳匹配是std::pair
复制构造函数,其中Foo
参数是const T2& y
,这导致调用了Foo
的复制构造函数。通过在Foo
的构造函数中添加explicit
,编译器拒绝了在匹配const T2& y
时隐式构造Foo
。 - tree