在 std::pair 支撑初始化中复制 vs 移动
Copy vs move in std::pair braced initialization
我有以下代码及其输出打印如下。我似乎无法理解为什么一组大括号初始化导致调用移动构造函数,而另一组导致调用复制构造函数。我已经将其缩小到直接列表初始化与复制列表初始化 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
,导致选择转发版本。
我有以下代码及其输出打印如下。我似乎无法理解为什么一组大括号初始化导致调用移动构造函数,而另一组导致调用复制构造函数。我已经将其缩小到直接列表初始化与复制列表初始化 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
,导致选择转发版本。