C++ 初始化列表 - 我不明白
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5153189/
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
C++ Initialization lists - I don't get it
提问by helpermethod
In Effective C++, it is said that data elements in the initialization list need to be listed in the order of their declaration. It is further said that the reasoning for this is that destructors for data elements get called in the reverse order of their constructors.
在 Effective C++ 中,据说初始化列表中的数据元素需要按照它们的声明顺序列出。进一步说,这样做的原因是数据元素的析构函数以其构造函数的相反顺序被调用。
But I just don't see how this could be a problem...
但我只是不明白这怎么会是一个问题......
回答by sharptooth
Well consider the following:
好考虑以下几点:
class Class {
Class( int var ) : var1( var ), var2(var1 ) {} // allright
//Class( int var ) : var2( var ), var1(var2 ) {} // var1 will be left uninitialized
int var1;
int var2;
};
The second (commented out) constructor looks allright, but in fact only var2
will be initialized - var1
will be initialized first and it will be initialized with var2
that is not yet initialized at that point.
第二个(注释掉的)构造函数看起来没问题,但实际上只会var2
被初始化 -var1
将首先被初始化,它将被初始化var2
为尚未初始化的那个点。
If you list initializers in the same order as member variables are listed in the class declaration risk of such errors becomes much lower.
如果您以与成员变量在类声明中列出的顺序相同的顺序列出初始化程序,则此类错误的风险会低得多。
回答by CygnusX1
The order of construction and destruction may be important when the members are also objects of some class that somehow depend on each other.
当成员也是某种以某种方式相互依赖的类的对象时,构造和销毁的顺序可能很重要。
Consider a simple example:
考虑一个简单的例子:
class MyString {
public:
size_t s_length;
std::string s;
MyString(const char *str) : s(str), s_length(s.length()) {}
};
The intention in this example is that member s_length
holds the length of the stored string. This will not work however, because s_length
will be initialised befores
. So you call s.length
before the constructor of s
is executed!
此示例中的意图是 members_length
保存存储字符串的长度。但是,这将不起作用,因为s_length
将在s
. 所以你s.length
在构造函数s
执行之前调用!
回答by flight
For example if you have a class like this:
例如,如果你有一个这样的类:
class X {
int a,b;
X(int i) : b(i),a(b) { } // Constructor
};
The constructor for class X looks like it initialises "b" first but it actually initialises in order of declaration. That means it will initialise "a" first. However "a" is initialised to the value of "b" which hasn't been initialised yet, so "a" will get a junk value.
类 X 的构造函数看起来像是先初始化“b”,但实际上是按照声明的顺序进行初始化的。这意味着它将首先初始化“a”。然而,“a”已初始化为尚未初始化的“b”值,因此“a”将获得垃圾值。
回答by CashCow
Destruction is the reverse of construction, therefore elements are destructed in reverse order.
破坏与构造相反,因此元素以相反的顺序被破坏。
Let us say we have 2 members, a
and b
. b
depends on a
but a
does not depend on b
.
假设我们有 2 个成员,a
并且b
. b
依赖于a
但a
不依赖于b
.
When we construct, we first construct a
and now it exists we can construct b
. When we destruct, if we destruct a
first this will be a problem as b
depends on it. But we destruct b
first and integrity is ensured.
当我们构造时,我们首先构造a
,现在它存在我们可以构造b
。当我们破坏时,如果我们a
先破坏,这将是一个b
取决于它的问题。但我们b
首先破坏并确保完整性。
This is typical. For example in group theory, the inverse of fg
is ~g~f
(where ~f
is the inverse of f
)
这是典型的。例如,在组理论,的倒数fg
就是~g~f
(其中~f
是的逆f
)
When you dress, you first put on socks and then you put on shoes. When you undress you first remove the shoes, then the socks.
穿衣时,先穿袜子,再穿鞋。脱衣服时先脱鞋,再脱袜子。
回答by phlipsy
It also could be a problem if one of the constructors of your members throws an exception. Then all members which were already properly constructed must be destructed in someorder because there isn't something similar to initializer-lists for destructors. This order is the reverse order of appearance of the members in the class declaration. An example:
如果您的成员的构造函数之一抛出异常,这也可能是一个问题。然后所有已经正确构造的成员必须按某种顺序被销毁,因为没有类似于析构函数的初始化列表的东西。此顺序与类声明中成员的出现顺序相反。一个例子:
#include <iostream>
struct A1 {
A1(int) { std::cout << "A1::A1(int)" << std::endl; }
~A1() { std::cout << "A1::~A1()" << std::endl; }
};
struct A2 {
A2(int) { std::cout << "A2::A2(int)" << std::endl; }
~A2() { std::cout << "A2::~A2()" << std::endl; }
};
struct B {
B(int) { std::cout << "B::B(int)" << std::endl; throw 1; }
~B() { std::cout << "B::~B()" << std::endl; }
};
struct C {
C() : a1(1), a2(2), b(3) { std::cout << "C::C()" << std::endl; } // throw 1; }
~C() { std::cout << "C::~C()" << std::endl; }
A1 a1;
A2 a2;
B b;
};
int main() {
try {
C c;
} catch (int i) {
std::cout << "Exception!\n";
}
}
The output will be something like this:
输出将是这样的:
A1::A1(int)
A2::A2(int)
B::B(int)
A2::~A2()
A1::~A1()
Exception!
回答by Chethan
It is further said that the reasoning for this is that destructors for data elements get called in the reverse order of their constructors.
进一步说,这样做的原因是数据元素的析构函数以其构造函数的相反顺序被调用。
See Steve Jessop's comment at Class component order of initialisation
请参阅 Steve Jessop 在Class component order of initialisation 中的评论