1

如果我通过使用创建临时对象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);
}

我访问后是否需要立即完成 A 的构造函数state

4

1 回答 1

4

A是的,该标准要求实现在访问之前执行构造函数的所有计算和副作用state


参考:

该表达式X(Y).Z是根据 C++11 的 5.2.5/1 的后缀表达式:

后缀表达式后跟一个点。或箭头 ->,可选地后跟关键字模板 (14.2),然后是 id 表达式,是后缀表达式。

该表达式X(Y)根据同一段落进行评估:

计算点或箭头之前的后缀表达式。64

64如果评估类成员访问表达式,即使结果对于确定整个后缀表达式的值是不必要的,例如如果 id-expression 表示静态成员,也会发生子表达式评估。

这就是 1.9/14 适用的地方:

与完整表达式关联的每个值计算和副作用在与要评估的下一个完整表达式关联的每个值计算和副作用之前排序。

X(Y)因此,一旦对点运算符进行评估,就会完成计算和副作用。

然而,这个表达式X根据 5.2.3/1 生成一个完全构造的对象:

[...] 该表达式T(x1, x2, ...)在效果上等同于T t(x1, x2, ...);某些发明的临时变量的声明t,其结果是tprvalue 的值。

和 12.2/3:

当实现引入具有非平凡构造函数(12.1、12.8)的类的临时对象时,它应确保为临时对象调用构造函数。[...] 临时对象作为评估完整表达式 (1.9) 的最后一步被销毁,该完整表达式 (从词法上) 包含创建它们的点。

即使尚未执行临时对象的实际创建(12.2/1),该标准也要求程序以这种方式运行:

即使临时对象的创建未被评估(第 5 条)或以其他方式避免(12.8),所有语义限制都应得到尊重,就好像临时对象已被创建并随后被销毁一样。

于 2014-02-04T14:00:37.793 回答