【问题标题】:order of evaluation of arguments to a constructor [duplicate]构造函数的参数评估顺序[重复]
【发布时间】:2013-06-29 23:20:41
【问题描述】:

假设我有这门课:

struct A
{
  A(int, int, int) {}
};

我这样初始化它:

A{ a(), b(), c() };

函数a()b()c() 都返回int。应该在b()b() 之前调用a()c() 之前调用吗?

我对标准中的以下段落感到困惑(8.5.4 [dcl.init.list] p4):

在花括号初始化列表的初始化列表中,初始化子句,包括任何由 pack 产生的子句 扩展(14.5.3),按照它们出现的顺序进行评估。也就是说,每个值计算和 与给定初始化子句相关的副作用在每个值计算和边之前排序 与在初始化器列表的逗号分隔列表中跟随它的任何初始化器子句相关联的效果。 [注意:无论初始化的语义如何,这种评估顺序都成立;例如,它适用 当初始化列表的元素被解释为构造函数调用的参数时,即使 通常对调用的参数没有顺序限制。 ——尾注]

根据引用,函数会按它们出现的顺序被调用,但是当我用我的编译器(g++-4.8.1)测试它时,它不成立。我是不是误会了什么?

【问题讨论】:

  • 谢谢,在构造函数中使用初始化列表似乎是解决方法。

标签: c++ c++11


【解决方案1】:

这是bug in GCC(感谢Casey 提供链接)。您引用的段落通常适用于列表初始化,其中术语在第 8.5.4/1 段中定义得非常清楚:

List-initialization 是从braced-init-list 初始化对象或引用。这样的初始化程序是 称为初始化器列表,列表中以逗号分隔的初始化器子句称为元素 初始化列表。

没有理由相信这应该只适用于初始化列表构造函数的调用。此外,您引用的段落中的注释澄清了:

这种求值顺序不管初始化的语义如何都成立;例如,它适用于初始化器列表的元素被解释为构造函数调用的参数时,即使调用的参数通常没有顺序约束。

【讨论】:

  • 这是GCC bug 51253
  • @Casey:好的,我不知道。感谢您的参考!
【解决方案2】:

小心你正在处理的事情。据我所知,您引用的报价仅适用于 初始化器列表。您正在使用的功能是统一初始化。它是初始化列表所必需的,但我怀疑它是否用于统一初始化。

【讨论】:

  • 引用确实提到了构造函数调用。你认为这句话只与使用初始化列表的构造函数相关吗?
  • 统一初始化是语法结构的非正式术语,称为花括号初始化列表。与std::initializer_list类型不同。
  • 并且引用的文本以“在括号初始化列表的初始化列表中”开头
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-05
  • 2012-08-22
  • 2010-11-17
  • 1970-01-01
相关资源
最近更新 更多