为什么结构体struct内部的类对象初始化方式与外部声明时不同?
初始化方式差异的核心原因
这个差异是C++标准对「非静态数据成员默认初始化器」的语法规则限制导致的,和Point类的构造函数设计无关:
- 两种初始化的场景属性完全不同
- main函数中的
Point myPoint(1, 1);属于普通局部变量的直接初始化,C++从最早的标准就支持小括号初始化语法,不存在语法歧义问题,所以可以正常使用。 - 结构体
segment内部的Point point1 = {0, 0};属于非静态数据成员的默认初始化器,这个特性是C++11版本才新增的,标准明确规定该场景下禁止使用小括号的初始化形式,仅支持两种合法写法:要么是= 初始值的形式,要么是纯花括号的列表初始化形式(比如直接写Point point1{0, 0};也符合语法)。
- 禁止小括号写法的根源是规避语法歧义
如果允许类/结构体成员用小括号初始化,会触发C++中著名的「最令人头疼的解析(most vexing parse)」问题,出现严重的语法解析二义性,比如代码int x(int());就有两种完全不同的解析结果:
解读1:声明一个int类型的成员变量x,用默认构造的int临时值(即0)初始化
解读2:声明一个成员函数x,返回值为int,入参是一个无参数、返回值为int的函数指针
为了从根源上避免这类歧义,C++标准直接限制了默认成员初始化器的语法形式,只允许花括号列表初始化或者等号赋值形式的初始化。
- 补充说明
你代码中使用的花括号初始化属于列表初始化,对于你实现的Point类来说,Point p{1,1}和Point p(1,1)的语义完全一致,都会调用对应的双参数构造函数,不存在功能、性能层面的差异,只是适用场景不同。
内容的提问来源于stack exchange,提问作者BaridunDuskhide
相关产品推荐
相关产品推荐

