【问题标题】:Class member initialization order, C++ [duplicate]类成员初始化顺序,C++ [重复]
【发布时间】:2018-02-22 13:45:08
【问题描述】:

所有旧的和现代的 C++ 书籍和专家都声明按声明顺序初始化类成员。但两者都没有解释如果我不这样做怎么办? 我不是在谈论具有 const 类型或 smth 成员的类。只是简单的类。

考虑示例:

class A
{
  int n;
  std::vector<double> VD;
  char c;
public:
  A():
      VD(std::vector<double>(3)),
      c('a'),
      n(44)
      {
      }
};

书面代码和声明顺序相同的代码有什么区别???

【问题讨论】:

  • 书籍我不知道,但至少cppreference.com告诉你:>列表中成员初始化器的顺序是无关:实际初始化顺序如下:...

标签: c++ class constructor initialization


【解决方案1】:

书面代码和声明顺序相同的代码有什么区别???

如果成员不依赖于彼此的初始化顺序,则没有任何区别。但如果他们这样做了,那么成员初始化列表可能在撒谎。

当许多程序员认为他们的构造函数写得正确时,他们被这一点所困扰,但实际上他们手上有未定义的行为。

考虑这个简单的案例:

struct foo {
  int _a;
  int _b;
  foo(int b) : _b(b), _a(2 * _b) {}
};

以上示例中的_a 是什么?如果您回答除了“行为未定义,因为_b 已使用初始化”,那么您就错了。

【讨论】:

  • 我很确定正在使用的 b 是参数而不是成员 - 但这正是为什么对 2 使用相同的名称并不好。
  • @UKMonkey - 易于重新引入的错误
  • @UKMonkey - 我什至不必使用new
  • 但是你可以!! foo(int b) : _b(new int(b)), _a(*b * 2) {} 正在研究如何在该行中删除它......我相信它会涉及逗号运算符
【解决方案2】:

但两者都没有解释如果我不这样做会怎样?

程序员无法控制它:您在初始化列表中列出成员的顺序对初始化的实际顺序没有影响。编译器会忽略列表中项目的顺序,并重新排序表达式以匹配声明顺序。

这里有一个简短的例子来说明这一点:

struct Foo {
    Foo(const char *s) { cout << "Init " << s << endl; }
};
struct Bar {
    Foo a;
    Foo b;
    Foo c;
    Bar() : c("c"), b("b"), a("a") {
    }
};

以上印刷品

Init a
Init b
Init c

即使初始化以相反的顺序列出项目。

Demo.

【讨论】:

    【解决方案3】:

    生成的程序集应该绝对没有区别,尽管“as-if”规则可能会妨碍。

    至少在概念上,nc 之前初始化。

    参考:http://en.cppreference.com/w/cpp/language/as_if

    【讨论】:

      【解决方案4】:

      您不能更改初始化顺序 - 这是成员在类中出现的顺序 - 初始化列表中的顺序并不重要,但如果两个顺序不匹配,编译器可能会发出警告。

      【讨论】:

        【解决方案5】:

        我认为正确订购它们有两个原因。

        1. 与声明它们的顺序相同,使代码更具可读性,尤其是当您想要添加或删除更多变量时。
        2. 声明它们的顺序表示它们在内存中的顺序。初始化变量时,您有更多的局部性。

        【讨论】:

        • 如果成员是private,则不一定在 (2) 上,尽管我对此并不绝对确定。像@StoryTeller 这样的专业人士有望证实。
        • @Bathsheba:当可见性混合时,可能会发生重新排序。
        • 具有相同可访问性的所有成员都按照声明的顺序排列。但不能保证具有不同可访问性的成员。
        • @StoryTeller:如果作者通过对它的 cmets 进行投票获得声誉就好了。
        • @Bathsheba - 我们得到了它的“权威”徽章。对我来说已经足够了:P
        【解决方案6】:

        这取决于成员的使用方式。如果存在依赖关系,则必须遵循顺序。

        考虑下面的例子。

            class x{
                 size_t n;
                 char * ch; // the size of dynamic char array depends on n
             }
        

        这里,以不同的顺序初始化会导致未定义的行为

        除了这个原因,可读性和统一性当然对编码指南 POV 很重要。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-03-30
          相关资源
          最近更新 更多