新的C ++ 11成员初始化特性是否在声明时使初始化列表过时了?
使用C ++ 11,我们现在可以在头文件声明中初始化类成员:
class aClass { private: int mInt{100}; public: aClass(); ~aClass(); };
所以我有点困惑。 传统上,构造函数中的初始化列表已被用于成员初始化:
aClass::aClass() : mInt(100) { ... }
新的C ++ 11成员初始化特性是否在声明时使初始化列表过时了? 如果不是的话,那么一个优于另一个呢? 什么情况会使声明初始化有利,或者初始化列表是否有利? 什么时候应该使用另一个?
不,它们不是过时的,因为这篇文章了解新的C ++ 11初始化表单在类成员初始化部分说( 重点是我的 ):
请记住,如果相同的数据成员在构造函数中同时具有类成员初始值设定项和mem-init项,则后者优先。 实际上,如果构造函数没有为该成员显式地使用mem-init,则可以通过以类成员初始值设定项的forms指定成员的默认值来利用此行为 。 否则,构造函数的mem-init将生效,覆盖类成员初始值设定项。 这个技巧在有多个构造函数的类中很有用
所以尽pipe在类成员初始化中是一个很好的方便,但它并不需要初始化列表,但是这两个特性相辅相成,给你一个很好的方法来指定默认值,并在需要时覆盖它们。 这似乎也是Bjarne Stroustrup也看到的,他说:
这节省了一些input,但真正的好处来自多个构造函数的类。 通常,所有构造函数都为一个成员使用一个通用的初始化方法:
并提供了一个具有共同初始值的成员的例子:
class A { public: A(): a(7), b(5), hash_algorithm("MD5"), s("Constructor run") {} A(int a_val) : a(a_val), b(5), hash_algorithm("MD5"), s("Constructor run") {} A(D d) : a(7), b(g(d)), hash_algorithm("MD5"), s("Constructor run") {} int a, b; private: HashingFunction hash_algorithm; // Cryptographic hash to be applied to all A instances std::string s; // String indicating state in object lifecycle };
并说:
hash_algorithm和s每个都有一个默认的事实在代码混乱中丢失,并且很容易成为维护期间的问题。 相反,我们可以将数据成员的初始化分解出来:
class A { public: A(): a(7), b(5) {} A(int a_val) : a(a_val), b(5) {} A(D d) : a(7), b(g(d)) {} int a, b; private: HashingFunction hash_algorithm{"MD5"}; // Cryptographic hash to be applied to all A instances std::string s{"Constructor run"}; // String indicating state in object lifecycle };
注意:在C ++ 11中是不利的
在C ++ 11中使用类成员初始化有一个缺点,因为它使得一个类是非聚合的,我们不能再使用聚合初始化 ,这可能是相当令人吃惊的。 在C ++ 14中,这个限制被删除的情况并非如此。 有关更多详细信息,请参阅: C ++ 11使用非静态成员初始值设定项对类进行聚合初始化 。
不,他们没有过时。
如果您需要构造函数参数来初始化您的类成员,初始化列表仍然是唯一的方法。
class A { int a=7; //fine, give a default value public: A(); }; class B { int b; public: B(int arg) : b(arg) {} B(int arg, bool b) : b(arg) { ... } };
请注意,如果两者都存在,构造函数的init将生效,覆盖类成员初始化,这有助于指定类成员的默认值。
在我看来,类内初始化是mem-initializer-lists的一个增强。 在C ++ 03中,未列在mem-initializer-list中的成员总是默认初始化。 这意味着类的默认构造函数,并且不对基元types进行初始化。
课堂上的初始化只是让你指定你自己的默认值。 有两种方法来看看它。
一:如果您的类的大多数/所有构造函数都想为成员提供相同的初始值,请为该成员使用类内构造函数。 对于其他成员,使用mem-initializer-lists。 只要初始值依赖于构造函数参数,就必须使用这些参数。
另一个:为所有成员提供一个类内初始化程序,你的类的默认构造函数如何初始化它们。 然后,非默认构造函数中的mem-initializer-lists将获得“它与默认构造对象的区别”的语义。