声明时新的 C++11 成员初始化功能是否使初始化列表过时?
使用 C++11,我们现在可以在头声明中初始化类成员:
With C++11, we now have the ability to initialize class members in a header declaration:
class aClass
{
private:
int mInt{100};
public:
aClass();
~aClass();
};
所以我有点困惑.传统上,构造函数中的初始化列表已用于成员初始化:
So I'm a bit confused. Traditionally initialization lists in constructors have been used for member initialization:
aClass::aClass()
: mInt(100)
{
...
}
声明时新的 C++11 成员初始化功能是否使初始化列表过时?如果不是,那么一个比另一个有什么优势?什么情况会使声明时的初始化有利,或者初始化列表有利?什么时候应该使用一个而不是另一个?
Has the new C++11 member initialization feature at declaration made initialization lists obsolete? If not, what are the advantages of one over the other? What situations would make initialization at declaration advantageous, or initialization lists advantageous? When should one be used over the other?
推荐答案
不,它们并没有像本文那样过时 了解新的 C++11 初始化形式 在类成员初始化部分中说(强调我的):
No, they are not obsolete as this article Get to Know the New C++11 Initialization Forms says in the Class Member Initialization section (emphasis mine):
请记住,如果同一个数据成员在构造函数中同时具有类成员初始化器和 mem-init,则后者优先.实际上,您可以通过以类成员初始化程序的形式为成员指定默认值来利用此行为,如果构造函数没有显式的 mem-init for那个成员.否则,构造函数的 mem-init 将生效,覆盖类成员初始化程序.此技术在具有多个构造函数的类中很有用
Bear in mind that if the same data member has both a class member initializer and a mem-init in the constructor, the latter takes precedence. In fact, you can take advantage of this behavior by specifying a default value for a member in the form of a class member initializer that will be used if the constructor doesn't have an explicit mem-init for that member. Otherwise, the constructor's mem-init will take effect, overriding the class member initializer. This technique is useful in classes that have multiple constructors
因此,尽管在类成员初始化中很方便,但它并没有消除对初始化列表的需要,但是这两个特性协同工作,为您提供了一种指定默认值并在需要时覆盖它们的好方法.这似乎也是 Bjarne Stroustrup 的看法,他说:
So although in class member initialization is a nice convenience it does not remove the need for initialization lists but both features instead work together to give you a nice way to specify default values and override them when needed. This seems to be also how Bjarne Stroustrup sees it too, he says:
这节省了一些输入,但真正的好处来自具有多个构造函数的类.通常,所有的构造函数都为一个成员使用一个通用的初始化器:
This saves a bit of typing, but the real benefits come in classes with multiple constructors. Often, all constructors use a common initializer for a member:
并提供具有通用初始化器的成员示例:
and provides an example of members which have a common initializer:
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 都有一个默认值这一事实在混乱的代码中丢失了,并且在维护期间很容易成为问题.相反,我们可以分解数据成员的初始化:
The fact that hash_algorithm and s each has a single default is lost in the mess of code and could easily become a problem during maintenance. Instead, we can factor out the initialization of the data members:
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 对具有非静态成员初始化程序的类的聚合初始化.
There is one disadvantage to using in class member initialization in C++11 since it makes a class a non-aggregate we can no longer use aggregate initialization which may be rather surprising. This is not the case in C++14 where this restriction was removed. See: C++11 aggregate initialization for classes with non-static member initializers for more details.
相关文章