initializer_list,构造函数和初始化初始化

时间:2018-10-30 10:57:10

标签: c++ c++11

在阅读有关不同类型的初始化的文章时,我偶然发现了std::initializer_list的众多怪异互动之一(上一篇文章here)。这显然是一个简单的主题,这是C ++书籍中出现std::vector时第一次出现的话题。

要点是,如果您有一个使用({我猜)} std::initializer_list的构造函数,则在进行括号初始化时,强烈建议使用该构造函数:换句话说,std::vector<int> NewVect{5, 10}将创建一个对象包含5和10,而不是5个元素初始化为10(std::vector<int> NewVect(5, 10))。

auto括号初始化发生特殊行为(auto A={1,2,3}被推导为std::initializer_list<int>)。现在,我不敢相信C ++会为特定的对象提供特殊的处理方式,因为据我所知,标头只是写得很好且有用的代码段。此外,即使您不直接或间接#include <initializer_list>,这些语法也不起作用,即使我的编译器VS2017会打印出一组非常特殊的错误,指出需要该标头才能正常工作(您可以轻松测试auto)。

所以,我的问题是,这是理所当然的,它是initiliazer列表头中代码的作用,而我的编译器可能是假定使用STD而构建的,它是如何实现的?我是否可以重新路由这种行为,使其在明确调用之外再也不会发生(即std::vector<int> NewVect{5, 10}等同于std::vector<int> NewVect(5, 10),而您现在需要调用std::vector<int> NewVect{std::initializer_list<int>{5, 10}})?可以将这种行为赋予其他用户创建的类吗?

1 个答案:

答案 0 :(得分:5)

  

理所当然的认为,此行为是initiliazer列表标题中代码的影响,而我的编译器可能是假定使用STD而构建的,如何实现?

标准中有一条特殊的规则,该规则类似于:“如果您使用列表初始化({...})来构造对象,并且该对象具有采用std::initializer_list无论是否具有超载分辨率,都选择该构造函数” 。这意味着在使用std::initializer_list初始化语法时,{...}构造函数始终比其他构造函数具有优先级。


  

我可以将这种行为重新路由为除显式调用之外永远不会发生

在课堂上,您可以避免使用std::initializer_list。那么这种行为将永远不会发生。您无法为std::个类更改此设置。


  

是否可以将此行为赋予其他用户创建的类?

不符合您期望的语法,因为std::initializer_list很特殊。您可以创建自己的initializer_list替代方案,或使用类似 variadic template 的构造函数来强制用户使用显式语法。