在阅读有关不同类型的初始化的文章时,我偶然发现了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}}
)?可以将这种行为赋予其他用户创建的类吗?
答案 0 :(得分:5)
理所当然的认为,此行为是initiliazer列表标题中代码的影响,而我的编译器可能是假定使用STD而构建的,如何实现?
标准中有一条特殊的规则,该规则类似于:“如果您使用列表初始化({...}
)来构造对象,并且该对象具有采用std::initializer_list
,无论是否具有超载分辨率,都选择该构造函数” 。这意味着在使用std::initializer_list
初始化语法时,{...}
构造函数始终比其他构造函数具有优先级。
我可以将这种行为重新路由为除显式调用之外永远不会发生
在课堂上,您可以避免使用std::initializer_list
。那么这种行为将永远不会发生。您无法为std::
个类更改此设置。
是否可以将此行为赋予其他用户创建的类?
不符合您期望的语法,因为std::initializer_list
很特殊。您可以创建自己的initializer_list
替代方案,或使用类似 variadic template 的构造函数来强制用户使用显式语法。