C++为何允许类内定义?是否违反ODR规则?相比构造函数初始化有何优势?
类内成员初始化与ODR规则相关问题解答
你给出的写法不会违反ODR规则,也不属于普通非静态成员的独立定义,以下是具体说明:
1. 该写法是不是类成员的实际定义?
你示例中写的是C++11标准正式引入的类内成员初始化器,仅属于对成员默认初始化值的声明,不是分配独立内存的定义:
普通非静态数据成员本身不属于全局独立实体,它的内存依附于类的实例对象存在,只有当你创建foo类的对象时,对象内的对应成员才会被实际定义、分配内存,类定义里写的初始值只是用来给初始化过程提供默认值而已。
比雅尼·斯特劳斯特鲁普提到的不允许类内定义的是「需要作为独立对象存储在内存中的实体」,指的是不带有inline修饰的静态成员变量,这类变量如果在类内定义会在多个引入头文件的翻译单元生成重复实例,才会违反ODR,和你示例中的普通非静态成员初始化场景完全不同。
2. 是否会违反ODR规则?
只要你保证所有引入该类定义的翻译单元中,类内的初始化器写法完全一致,就不会违反ODR(单一定义规则):
ODR对类的要求是多个翻译单元中的类定义必须完全等同,类内成员初始化器本身就是类定义的合法组成部分,只要符合「多翻译单元下类定义完全一致」的要求,就不会触发ODR冲突。
3. 相比构造函数初始化的优势
这种写法是现代C++非常推荐的写法,优势非常明显:
- 减少重复代码:如果类有多个重载的构造函数,不需要在每个构造函数的初始化列表中重复写相同的成员初始值,统一在类内声明一次即可,避免冗余。
- 可读性更强:成员的声明和默认初始值直接绑定,阅读类定义时就能直接看到每个成员的默认取值,不需要跳转查看各个构造函数的实现。
- 降低维护出错概率:后续新增类成员时,只要在类内给出默认初始值,不需要修改所有已有的构造函数,不会出现新增成员未在旧构造函数中初始化的低级错误。
- 适配聚合初始化场景:C++17起允许聚合类使用类内初始化器,既可以享受默认初始化的兜底,也可以在创建对象时手动覆盖部分成员的取值,使用更灵活。
你给出的参考代码:
class foo { float f = 1.1f; int i = 1; string s = "foo"; long long ll = 44ll; };
内容的提问来源于stack exchange,提问作者mada
相关产品推荐
相关产品推荐

