如果使用class-type-name(parameters).member
创建临时对象并假定构造函数已完成,是否可以访问对象的成员?
考虑以下示例:
struct A
{
enum status
{ ERROR = -1, SUCCESS } state;
A (int a)
: state(a > 0 ? SUCCESS : ERROR)
{
// do some stuff here
// may change state
}
};
int main (void)
{
// Is this guaranteed to work?
A::status S(A(5).state);
}
一旦访问state
,是否需要完成A的构造函数?
答案 0 :(得分:4)
是的,该标准要求实现在访问A
之前执行state
的构造函数的所有计算和副作用。
表达式X(Y).Z
是一个Postfix表达式,符合5.2.5 / 1的C ++ 11:
后缀表达式后跟一个点。或箭头 - >,可选地后跟关键字模板(14.2),然后是id-expression,是后缀表达式。
表达式X(Y)
按照同一段落进行评估:
评估点或箭头前的后缀表达式。 64
64 :如果计算了类成员访问表达式,则即使不需要结果来确定整个后缀表达式的值,也会发生子表达式求值,例如,如果id- expression表示静态成员。
这是适用于1.9 / 14的地方:
在每个值计算和与要评估的下一个完整表达式相关的副作用之前,对与全表达式相关的每个值计算和副作用进行排序。
因此,X(Y)
的计算和副作用在评估点运算符后立即完成。
然而,该表达式根据5.2.3 / 1:
生成完全构造的对象X
[...]表达式
T(x1, x2, ...)
与某些发明的临时变量T t(x1, x2, ...);
的声明t
等效,其结果是t
的值作为一个prvalue。
和12.2 / 3:
当实现引入具有非平凡构造函数(12.1,12.8)的类的临时对象时,它应确保为临时对象调用构造函数。 [...]临时对象作为评估全表达式(1.9)的最后一步被销毁,该表达式(词法上)包含创建它们的点。
该标准要求程序以这种方式运行,即使尚未执行临时对象的实际创建(12.2 / 1):
即使临时对象的创建未被评估(第5条)或以其他方式避免(12.8),也应尊重所有语义限制,就像临时对象已被创建并随后被销毁一样。