C++ const 引用初始化和大括号语法

C++ const reference initalization and curly braces syntax

我对使用 {} 初始化常量引用有点困惑。 所以这是我的代码:

#include <iostream>
#include <initializer_list>

template <typename T>
class Test
{
public:
  Test(std::initializer_list<T> l)
  {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
  }
  Test(const Test<T>& copy)
  {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
  }
  Test() = delete;
};

int main()
{
  Test<int> t1 {100500};

  //here temporary constructed with copy constructor
  //ref1 bound to temporary
  const auto& ref1 = {t1};

  //no temporary, ref2 bound to t1
  const Test<int>& ref2 = {t1};

  //temporary constructed with copy constructor
  //ref3 bound to temporary
  const Test<int>& ref3 = {{t1}};

  return 0;
}

我困惑的根源是这 3 个初始化的不同行为。看起来他们做不同的事情并遵循不同的规则。有人可以澄清每种情况下到底发生了什么吗?

我的OS:

Linux Mint 19 Tara

编译器:

gcc 7.3.0

编译命令:

g++ -std=c++11 -O0 test.cpp -o test -Wall -pedantic

对于const auto& ref1 = {t1}

执行复制列表初始化,ref1的推导类型为std::initializer_list<Test<int>>,在此过程中对其元素进行复制初始化,调用Test<int>复制构造函数。

注意:你在ref1里面的评论可能会误导你,临时绑定到ref1的不是Test<int>类型的是类型 std::initializer_list<Test<int>>.

const Test<int>& ref2 = {t1}

这是在复制列表初始化的上下文中引用绑定有一个特殊的规则,引用绑定用一个元素的大括号初始化,引用直接绑定,没有临时引入。

const Test<int>& ref3 = {{t1}}

此时引用不直接绑定,{t1}需要转换成类型绑定引用,{t1}复制初始化一个临时的(Test<int>复制构造函数调用)并且该临时用于初始化 ref3.