C++ 类括号初始化被误解为std::initializer\u列表,而不是复制构造
考虑以下C++11代码:C++ 类括号初始化被误解为std::initializer\u列表,而不是复制构造,c++,c++11,gcc,C++,C++11,Gcc,考虑以下C++11代码: #include <initializer_list> struct MyStruct { MyStruct() {} MyStruct(const MyStruct& other) {} void doStuff() const {} }; int main() { MyStruct a; auto b{a}; a.doStuff(); b.doStuff(); return 0
#include <initializer_list>
struct MyStruct {
MyStruct() {}
MyStruct(const MyStruct& other) {}
void doStuff() const {}
};
int main() {
MyStruct a;
auto b{a};
a.doStuff();
b.doStuff();
return 0;
}
#包括
结构MyStruct{
MyStruct(){}
MyStruct(const MyStruct&other){}
void doStuff()常量{}
};
int main(){
我的结构a;
自动b{a};
a、 doStuff();
b、 doStuff();
返回0;
}
我原以为b
是MyStruct
的一个实例,副本是由a
构建的,但是当使用GCC 4.9.1编译时,b
是一个std::initializer
。GCC 8.2按照预期编译了该文件
注意我在锁销上举了一个例子:
你能解释一下这两个编译器版本之间的区别吗?(或者标准的状态是什么?)< P> > P >这是C++ 11中的预期行为: 在以下情况下,将自动构造std::initializer\u list对象: ... 大括号的init列表绑定到auto,包括在ranged for循环中 因此,当您将
{x1,x2,…,xn}
分配给“auto”时,如果所有值都具有相同的类型,您将得到类型为std::initializer\u list
的对象(为了简单起见,我在这里跳过引用和cv):
auto a={5};//std::初始值设定项列表
自动b{5};//std::初始值设定项列表
自动c={1,2};//std::初始值设定项列表
自动d{1,2};//std::初始值设定项列表
然而,在C++17中,这一点被改变了。增加了以下规则:
- 对于复制列表初始化,自动扣减将推导出 如果列表中的所有元素都具有相同的 类型,或格式不正确
- 对于直接列表初始化,如果列表只有一个元素,则自动推断将推断出一个T,如果有多个元素,则自动推断将是格式错误的 一个因素
auto a = {42}; // std::initializer_list<int>
auto b {42}; // int
auto c = {1, 2}; // std::initializer_list<int>
auto d {1, 2}; // error, too many
auto a={42};//std::初始值设定项列表
自动b{42};//int
自动c={1,2};//std::初始值设定项列表
自动d{1,2};//错误,太多了
我相信gcc 8.2在这种情况下不能正确处理-std=c++11这是c++11中的一个bug,在c++14中修复了它。看起来GCC 8.2正在考虑新规则,即使你正在用C++ 11标志编译。 新角色说: 对于直接列表初始化:
- 对于只有一个元素的带括号的init列表,自动推断将 从该条目开始李>
- 对于包含多个元素的大括号init列表,自动推断的格式将不正确
MyStruct a;
auto b{a};
它遵循第一条规则,这就是它编译没有问题的原因
老一代的GCC 4.91没有实现这些新的规则,所以默认的是它认为是<代码> STD::IngaliSeriSList./P>但是为什么编译器的两个版本之间的差异呢?有趣的怪癖!我想我们可以称之为怪癖:D谢谢你的澄清!
MyStruct a;
auto b{a};