std::initializer_list 是否有复制构造函数,是否曾经使用过?

Does std::initializer_list have a copy constructor and is it ever used?

本文关键字:是否 曾经 复制 initializer list std 构造函数      更新时间:2023-10-16

std::initializer_list是否有复制构造函数,如果有,它是否会被使用,在哪些情况下? 因为我注意到以下内容无法在 GCC 中编译:

std::initializer_list<int>{{1,2,3,4}};

而下面的那个确实

class Test{
public:
Test(const std::initializer_list<int> &){}
};
Test{{1,2,3,4,5,6}};

所以我怀疑如果 std::initializer_list具有 Test 类具有的构造函数,则第一段代码将编译

所以我怀疑如果 std::initializer_list具有 Test 类具有的构造函数,第一段代码将编译

这将假设"统一初始化"实际上是统一的,这始终是一个危险的假设。

initializer_list对从大括号初始化列表构造有特殊规则。如果你将大括号的 init-list 应用于一个initializer_list<T>,那么 [dcl.init.list]/3.5 就会启动,它说"下面",跳过其余的子段落。"下面"说:

类型std​::​initializer_­list<E>的对象是从初始值设定项列表构造的,就好像实现生成并具体化了类型为"Nconst E数组"的 prvalue,其中N是初始值设定项列表中的元素数。

好吧,您正在从单个元素构造initializer_list<int>,该元素本身就是一个大括号的初始化列表。该大括号初始化列表现在应用于E,这是int。而且由于该列表有多个条目,因此不起作用。

由于第 3.5 项明确跳过了该节中的所有其他小段,因此该内部大括号的 init-list 是否可以创建initializer_list<int>并不重要。编译器从不检查这一点,因为要这样做的检查是在 3.6 中,它被跳过了。


作为记录,initializer_list确实具有(默认)复制/移动构造函数和赋值运算符。

根据 cpp首选项,唯一可用的构造函数是默认构造函数。

这可能与它通常的实现方式有关:一个标准的C式数组。 有关其他信息,我将推荐Jason Turner在CppCon2018上的这段视频,该视频提供了对生命周期的见解。

但是,您可以使用initializer_list有效地将容器视为其"副本"来初始化容器。