复制vs in std :: pair支持初始化

问题描述 投票:1回答:1

我有以下代码,其输出显示在下面。我似乎无法理解为什么一组支撑初始化会导致调用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
c++ templates initialization move-semantics std-pair
1个回答
1
投票

让我们看一下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,因此推导U2Foo,从而选择转发版本。

© www.soinside.com 2019 - 2024. All rights reserved.