我有以下代码,其输出显示在下面。我似乎无法理解为什么一组支撑初始化会导致调用move构造函数,而另一组导致复制构造函数。我已将其范围缩小为每个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
让我们看一下pair
的两个参数的两个构造函数:[pairs.pair]
EXPLICIT constexpr pair(const T1& x, const T2& y);
template<class U1, class U2> EXPLICIT constexpr pair(U1&& x, U2&& y);
第二个构造函数使用完美的转发,并且无法从U2
推导出{}
。因此,使用{}
时选择第一个版本。改为使用Foo{}
时,参数的类型为Foo
,因此推导U2
为Foo
,从而选择转发版本。