C++98模板结构体默认成员初始化导致对象初始化失败的原因咨询
C++98模板结构体默认成员初始化导致对象初始化失败的原因咨询
嘿,这个问题其实和C++标准的演进直接相关,咱们一步步拆解来看:
首先要明确一个核心点:C++98完全不支持非静态成员的类内默认初始化(就是你写T first = 0;这种给成员直接赋初始值的语法),这是C11才正式引入的特性。你的报错本质上是这个语法在C98下不合法,进而引发了后续的初始化问题。
咱们具体分析两种情况:
带类内默认初始化的代码(C++98下报错)
当你在C++98环境中写:
template <typename T> struct Pair { T first = 0; T second = 0; };
编译器会直接判定T first = 0;这种写法非法——因为C++98只允许静态const成员在类内初始化,非静态成员必须通过构造函数来设置初始值。
而你尝试用Pair<int> p1 { 5, 6 };这种列表初始化时,在C++98中,只有聚合类型才能使用这种初始化方式。聚合类型的要求包括:没有用户声明的构造函数、没有类内成员初始化器、没有基类等。但因为你的代码里用了非法的类内默认初始化,编译器在处理时会混乱:它既不认可这种初始化语法,又无法将Pair识别为合法的聚合类型,最终找不到能匹配{5,6}的构造函数,就抛出了no matching function for call to 'Pair<int>::Pair()'的错误。
去掉类内默认初始化的代码(C++98下正常工作)
当你把成员声明改成:
template <typename T> struct Pair { T first; T second; };
此时Pair在C++98下完全符合聚合类型的定义:没有用户构造函数、没有非法的类内初始化器、是简单的结构体。这时候Pair<int> p1 {5,6};就属于标准的聚合初始化——编译器会直接把大括号里的5和6分别赋值给first和second,自然就能正常编译运行了。
为什么C++11及以后没问题?
C++11做了两个关键改进:
- 引入了非静态成员的类内默认初始化特性,允许你直接给成员赋初始值;
- 完善了**统一初始化(列表初始化)**的规则,带类内默认初始化的结构体依然可以被识别为聚合类型(C11到C14的规则),所以
{5,6}可以直接覆盖默认值完成初始化,赋值语句p1 = {2,3};也属于合法的列表赋值操作。
备注:内容来源于stack exchange,提问作者Orpicon
相关产品推荐
相关产品推荐

