构造函数参数的求值顺序
order of evaluation of arguments to a constructor
假设我有这个类:
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列表中的对象或引用的初始化。这样的初始化器是称为初始值设定项列表,列表中逗号分隔的初始化项子句称为初始值设定项列表。
没有理由相信这应该只适用于初始值设定项列表构造函数的调用。此外,你引用的段落中的注释澄清了:
无论初始化的语义如何,此求值顺序都保持不变;例如,当初始值设定项列表的元素被解释为构造函数调用的参数时,即使调用的参数通常没有排序约束,它也适用。
小心你正在处理的事情。据我所见,您引用的引号仅适用于初始值设定项列表。您正在使用的功能是统一初始化。它是初始化器列表所必需的,但我怀疑它是否用于统一初始化。
- 函数调用中参数的顺序重要吗
- C++部分概念 id:显式模板规范顺序/第一个参数的特殊状态的原因是什么?
- lambda 作为接受其他参数的参数的初始化顺序
- 运算符 new 的执行顺序和构造函数的参数
- 如何检查参数包是否具有执行顺序中的确切类型
- std::bind() 参数列表中函子的执行顺序(可能与函数参数的求值顺序无关)
- 构造函数中没有参数的对象类成员按什么顺序初始化?
- 如何实现对参数顺序不可知的std::same_as的广义形式(即对于两个以上的类型参数)
- 用作成员构造函数参数的函数的求值顺序
- C++17的可选和可变顺序函数参数
- 委派的 ctor 是否受参数计算顺序的影响?
- x64 函数调用参数推送/移动顺序 (MSVC)
- 函数参数计算顺序与 Lambda 捕获评估顺序
- 反转模板(整数)参数的顺序
- 大括号和括号之间的参数计算顺序
- 约束模板参数顺序的更简单方法
- C++ 更改基于参数设置的默认顺序
- 重载运算符以允许C++中参数的不同顺序
- 正确对齐内存模板,参数顺序不变
- 为具有默认值的非顺序参数函数创建启动器