构造函数参数的求值顺序

order of evaluation of arguments to a constructor

本文关键字:顺序 参数 构造函数      更新时间:2023-10-16

假设我有这个类:

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

我这样初始化它:

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

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

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

在支撑的init列表的initializer列表中,initializer子句,包括从pack产生的任何子句膨胀(14.5.3)按它们出现的顺序进行评估。也就是说,每个值的计算和与给定初始值设定项子句相关的副作用在每次值计算和副作用之前进行排序在初始值设定项列表的逗号分隔列表中,与其后的任何初始值设定项子句关联的效果。[注意:无论初始化的语义如何,此求值顺序都适用;例如,它适用当初始值设定项列表的元素被解释为构造函数调用的参数时,即使通常,调用的参数没有顺序约束。——尾注]

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

这是GCC中的一个错误(感谢Casey提供的链接)。您引用的段落通常适用于列表初始化,其中术语在第8.5.4/1:段中定义非常明确

列表初始化是对支持的init列表中的对象或引用的初始化。这样的初始化器是称为初始值设定项列表,列表中逗号分隔的初始化项子句称为初始值设定项列表。

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

无论初始化的语义如何,此求值顺序都保持不变;例如,当初始值设定项列表的元素被解释为构造函数调用的参数时,即使调用的参数通常没有排序约束,它也适用。

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