我可以访问临时对象的成员吗?

时间:2014-02-04 14:00:38

标签: c++ member temporary-objects

如果使用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的构造函数?

1 个答案:

答案 0 :(得分:4)

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

<小时/>

参考:

表达式X(Y).Z是一个Postfix表达式,符合5.2.5 / 1的C ++ 11:

  

后缀表达式后跟一个点。或箭头 - &gt;,可选地后跟关键字模板(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),也应尊重所有语义限制,就像临时对象已被创建并随后被销毁一样。