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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 17:31:46  来源:igfitidea点击:

C++ Initialization lists - I don't get it

c++initialization-list

提问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 var2will be initialized - var1will be initialized first and it will be initialized with var2that 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_lengthholds the length of the stored string. This will not work however, because s_lengthwill be initialised befores. So you call s.lengthbefore the constructor of sis executed!

此示例中的意图是 members_length保存存储字符串的长度。但是,这将不起作用,因为s_lengths. 所以你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, aand b. bdepends on abut adoes not depend on b.

假设我们有 2 个成员,a并且b. b依赖于aa不依赖于b.

When we construct, we first construct aand now it exists we can construct b. When we destruct, if we destruct afirst this will be a problem as bdepends on it. But we destruct bfirst and integrity is ensured.

当我们构造时,我们首先构造a,现在它存在我们可以构造b。当我们破坏时,如果我们a先破坏,这将是一个b取决于它的问题。但我们b首先破坏并确保完整性。

This is typical. For example in group theory, the inverse of fgis ~g~f(where ~fis 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 中的评论