c++ - 在 std::pair 支撑初始化中复制 vs move

标签 c++ templates initialization move-semantics std-pair

我有以下代码及其输出打印如下。我似乎无法理解为什么一组大括号初始化导致调用 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,导致选择转发版本。

关于c++ - 在 std::pair 支撑初始化中复制 vs move ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61151479/

相关文章:

c++ - C++ 中的模板

c++ - boost::mutex 在模板中使用时不起作用

c++ - g++ 中 ">"之前的预期主表达式,但在微软编译器中没有

objective-c - 如何在快速便捷的初始化程序中返回自定义对象?

c++ - Makefile - main.o 未创建,但编译正常

python - 修改静态变量是线程安全的吗?

c++ - qt4宏检测KDE或GNOME

c++ - 如何让模板推导其参数

c++ - 聚合结构构造函数

java - 为什么实例初始化 block 在构造函数之前执行