声明时新的 C++11 成员初始化功能是否使初始化列表过时了?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24149924/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Has the new C++11 member initialization feature at declaration made initialization lists obsolete?
提问by Vector
With C++11, we now have the ability to initialize class members in a header declaration:
使用 C++11,我们现在可以在头声明中初始化类成员:
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)
{
...
}
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 成员初始化功能是否使初始化列表过时了?如果不是,一个比另一个有什么优势?什么情况会使声明时初始化或初始化列表有利?什么时候应该使用一个?
回答by Shafik Yaghmour
No, they are not obsolete as this article Get to Know the New C++11 Initialization Formssays in the Class Member Initializationsection (emphasis mine):
不,它们并没有过时,因为本文了解新的 C++11 初始化形式在类成员初始化部分(重点是我的)中说:
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 memberin 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
请记住,如果同一个数据成员在构造函数中同时具有类成员初始值设定项和 mem-init,则后者优先。实际上,您可以通过以类成员初始值设定项的形式为成员指定默认值来利用此行为,如果构造函数没有该成员的显式 mem-init,则将使用该值。否则,构造函数的 mem-init 将生效,覆盖类成员初始值设定项。此技术在具有多个构造函数的类中很有用
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 Stroustrupsees it too, he says:
因此,尽管在类成员中初始化是一个很好的便利,但它并没有消除对初始化列表的需要,而是两个功能一起工作,为您提供了一种指定默认值并在需要时覆盖它们的好方法。这似乎也是Bjarne Stroustrup 的看法,他说:
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
};
and says:
并说:
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:
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
};
Note: disadvantage in C++11
注意: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 initializationwhich 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 initializersfor more details.
在 C++11 中使用类成员初始化有一个缺点,因为它使类成为非聚合我们不能再使用聚合初始化,这可能会令人惊讶。在删除此限制的 C++14 中,情况并非如此。有关更多详细信息,请参阅:具有非静态成员初始值设定项的类的 C++11 聚合初始化。
回答by quantdev
No, they are not obsolete.
不,它们并没有过时。
Initialization lists are still the only way to go if you need constructors arguments to initialize your class members.
如果您需要构造函数参数来初始化您的类成员,初始化列表仍然是唯一的方法。
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) { ... }
};
Note that if both are present, the constructor's init will take effect, overriding the class member initialization, which is useful to specify a default value for a class member.
请注意,如果两者都存在,则构造函数的 init 将生效,覆盖类成员初始化,这对于为类成员指定默认值很有用。
回答by Angew is no longer proud of SO
The way I look at it, in-class initialization is an ehancement of mem-initializer-lists. In C++03, members not listed in a mem-initializer-list were always default initialised.This means the default constructor for classes, and no initialization for primitive types.
在我看来,类内初始化是对 mem-initializer-lists 的增强。在 C++03 中,未在 mem-initializer-list 中列出的成员始终默认初始化。这意味着类的默认构造函数,原始类型没有初始化。
In-class initialization simply allows you to specify your own defaults. There are two ways to look at it.
类内初始化仅允许您指定自己的默认值。有两种方法可以查看它。
One: if most/all constructors of your class want to provide the same initial value for a member, use an in-class initializer for that member. For other members, use mem-initializer-lists. You'll of course have to use those whenever the initial value depends on constructor arguments.
一:如果您的类的大多数/所有构造函数都希望为成员提供相同的初始值,请为该成员使用类内初始化程序。对于其他成员,请使用 mem-initializer-lists。当初始值取决于构造函数参数时,您当然必须使用它们。
The other one: provide an in-class initializer for all members, exactly how the default constructor of your class would initialise them. Then, mem-initializer-lists in non-default constructors get the semantics of "how it differs from a default-constructed object."
另一个:为所有成员提供一个类内初始化器,确切地说你的类的默认构造函数如何初始化它们。然后,非默认构造函数中的 mem-initializer-list 获得“它与默认构造的对象有何不同”的语义。