可以使用成员变量在初始化列表中初始化其他成员吗?

发布于 2025-02-13 13:07:07 字数 378 浏览 1 评论 0原文

考虑以下(简化的)情况:

class Foo
{
private:
    int evenA;
    int evenB;
    int evenSum;
public:
    Foo(int a, int b) : evenA(a-(a%2)), evenB(b-(b%2)), evenSum(evenA+evenB)
    {
    }
};

当我这样实施foo时:

Foo foo(1,3);

然后偶数为0,偶数为2,但是evensum是否会初始化为2?

我在当前平台(iOS)上尝试了此操作,但它似乎有效,但是我不确定此代码是否可移植。

感谢您的帮助!

Consider the following (simplified) situation:

class Foo
{
private:
    int evenA;
    int evenB;
    int evenSum;
public:
    Foo(int a, int b) : evenA(a-(a%2)), evenB(b-(b%2)), evenSum(evenA+evenB)
    {
    }
};

When i instanciate Foo like this:

Foo foo(1,3);

then evenA is 0, evenB is 2, but will evenSum be initialized to 2?

I tried this on my current platform (iOS) and it seems to work, but I'm not sure whether this code is portable.

Thanks for your help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

ぃ双果 2025-02-20 13:07:07

良好的便携式, 1 ,但可能容易出错。

成员按在班级正文中声明的顺序初始化,而不是初始化列表中列出的顺序。因此,如果您更改班级主体,则此代码可能会默默失败(尽管许多编译器会发现这一点并发出警告)。


1. From [class.base.init] in the C++ standard(s):

在非规定的构造函数中,初始化按以下顺序进行:

  • 首先,仅对于最派生类(1.8)的构造函数,虚拟基类都在
    它们出现在对基类的定向无环图的深度最深处的横向遍历上,
    其中“从左到右”是派生的类基准列表中基类的外观顺序。
  • 然后,直接基类以声明顺序初始化,因为它们出现在基本列表中
    (不管Mem-Initializer的顺序如何)。
  • 然后,非静态数据成员以类别定义中声明的顺序初始化初始化
    (再次不论MEM-Initializer的顺序)。
  • 最后,执行了构造体的复合态。

(突出显示是我的。)

随后,标准的这一部分继续提供一个使用成员变量来初始化其他成员变量的示例。

This is well-defined and portable,1 but it's potentially error-prone.

Members are initialized in the order they're declared in the class body, not the order they're listed in the initialization list. So if you change the class body, this code may silently fail (although many compilers will spot this and emit a warning).


1. From [class.base.init] in the C++ standard(s):

In a non-delegating constructor, initialization proceeds in the following order:

  • First, and only for the constructor of the most derived class (1.8), virtual base classes are initialized in
    the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes,
    where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.
  • Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list
    (regardless of the order of the mem-initializers).
  • Then, non-static data members are initialized in the order they were declared in the class definition
    (again regardless of the order of the mem-initializers).
  • Finally, the compound-statement of the constructor body is executed.

(Highlighting is mine.)

This section of the standard then goes on to give an example of using member variables to initialize other member variables.

等往事风中吹 2025-02-20 13:07:07

是的,提供它们已经建成。只是不要忘记
施工顺序是声明的顺序
班级定义,不是
构造函数。而且编译器通常不会告诉您是否使用
在构造它之前。例如,在您的情况下,
如果您将evensum移动到班级的顶部,则您的未定义
行为(因为其初始化器使用非初始化的成员),甚至
尽管在构造函数中,您可以初始化evenaevenb词汇
evensum之前。

Yes, provide they've already been constructed. Just don't forget
that the order of construction is the order of the declarations in the
class definition, not the order of the initializers in the
constructor. And that the compiler typically won't tell you if you use
a variable before it has been constructed. In your case, for example,
if you move evenSum to the top of the class, you have undefined
behavior (because its initializer uses uninitialized members), even
though in your constructor, you initialize evenA and evenB lexically
before evenSum.

情泪▽动烟 2025-02-20 13:07:07

成员按在类定义中声明的顺序初始化。只要您的初始化列表遵循此订单,就可以了。

Members are initialized in the order they're declared in the class definition. As long as your initializer list follows this order, it should be ok.

叶落知秋 2025-02-20 13:07:07

调用初始化器的顺序
初始化顺序

列表中成员初始化器的顺序无关紧要:初始化的实际顺序如下:

  1. 如果构造函数适用于最衍生的类,则以其在基类声明的深度左右横向遍历的顺序中初始化虚拟基础(从左到右是指外观在基本分类器列表中)
  2. 然后,直接基地以从左到右的顺序初始化,因为它们出现在该班级的基本指定列表中
  3. 然后,非静态数据成员按班级定义中的声明顺序初始化。
  4. 最后,执行构造函数的主体

,所以是的,只要evena and evenbevensum之前声明 evenb

The order in which initializers are called:
Initialization order

The order of member initializers in the list is irrelevant: the actual order of initialization is as follows:

  1. If the constructor is for the most-derived class, virtual bases are initialized in the order in which they appear in depth-first left-to-right traversal of the base class declarations (left-to-right refers to the appearance in base-specifier lists)
  2. Then, direct bases are initialized in left-to-right order as they appear in this class's base-specifier list
  3. Then, non-static data member are initialized in order of declaration in the class definition.
  4. Finally, the body of the constructor is executed

So yes, your example will work, as long as evenA and evenB are declared before evenSum

岁月苍老的讽刺 2025-02-20 13:07:07

这也在G ++ 4.0.3(现在6岁)上进行了编译。

我有信心在任何合理的编译器上都可以纠正。

This also compiled without error on g++ 4.0.3 (6 years old now).

I feel confident this will compile fine on any reasonably recent compiler.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文