由这个答案触发,我正在读核心准则
C.45:不要定义只初始化数据成员的默认构造函数,而是使用类中的成员初始化器。
给出的理由是
原因 使用类内成员初始化器可以让编译器为您生成函数.编译器生成的函数可以更高效。
请注意,这是专门针对默认构造函数的,它只会初始化成员,并且指导原则建议,一个不应该编写这样的构造函数。
“坏”的例子是:
例如,bad类X1 { // BAD:不使用成员初始化器字符串s;int i;public: X1():s{“默认”},i{1} {} // . };
“很好”的例子是使用类中的成员初始化器,而没有用户声明的构造函数:
示例类X2 { string s= " default ";int = 1;public: // use编译器生成的默认构造函数// . };
编译器生成的构造函数可以比用户提供的构造函数在特定示例(或任何其他示例中)中做得更高效吗?
初始化程序列表是否没有提供与类初始化器相同的优化机会?
发布于 2021-01-21 10:56:45
我认为,假设C.45引用常量(示例和强制执行)是很重要的:
例如,坏 类X1 { // BAD:不使用成员初始化器字符串s;int i;public: X1():s{“默认”},i{1} {} // . }; 示例 类X2 { string s= " default ";int = 1;public: // use编译器生成的默认构造函数// . }; 强制执行 (简单)默认构造函数不应该仅仅使用常量初始化成员变量。
考虑到这一点,我们更容易(通过C.48)对常量而言,在构造函数中使用类内初始化器而不是成员初始化器:
C.48:对于常量初始化器,类内初始化器比构造函数中的成员初始化器更好。 原因 使所有构造函数都期望使用相同的值。避免重复。避免维护问题。它会导致最短和最有效的代码。 例如,坏 类X{ // BAD int i;string s;int j;public: X() :i{666},s{"qqq"} {} /j是未初始化的X(int ii) :i{ii} {} // s is“和j是未初始化// . }; 维护人员如何知道j是否是故意未初始化的(不管怎么说,这可能是个糟糕的主意),以及在一种情况下是否有意给出默认值"“,在另一种情况下给出qqq (几乎肯定是一个bug)?当一个新成员被添加到一个现有的类中时,j(忘记初始化一个成员)的问题经常发生。 示例 类X2 { int i {666};字符串s {"qqq"};int j {0};public: X2() =X2;//所有成员初始化为默认值X2(int ii) :i{ii} {} // s,j初始化为默认值// . }; 可选方案:我们可以从构造函数的默认参数中获得部分好处,这在旧代码中并不少见。但是,这不那么明确,会导致更多的参数被传递,并且在有多个构造函数时是重复的: 类X3 { // BAD:不显式,参数传递开销int i;string s;int j;public: X3(int ii = 666,const string& ss = "qqq",int jj = 0) :i{ii},s{ss},j{jj} {} //所有成员初始化为默认值// . }; 强制执行 (简单)每个构造函数都应该初始化每个成员变量(显式地,通过委托ctor调用,或者通过默认方式)。 建筑)。(简单)构造函数的默认参数表明类内初始化程序可能更合适。
https://stackoverflow.com/questions/56272431
复制相似问题