C++中const引用的初始化和花括号语法

3

我在使用 {} 初始化常量引用时有些困惑。这是我的代码:

#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种初始化方式的不同行为。看起来它们执行不同的操作并遵循不同的规则。能否有人澄清每种情况下究竟发生了什么?
我的操作系统:
Linux Mint 19 Tara
编译器:
gcc 7.3.0
编译命令:
g++ -std=c++11 -O0 test.cpp -o test -Wall -pedantic
1个回答

3

对于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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接