我们可以访问不存在的类类型对象的成员吗?

时间:2018-11-05 09:25:21

标签: c++ language-lawyer strict-aliasing class-members

在c ++标准中,[basic.lval]/11.6中说:

  

如果程序尝试通过以下类型之一以外的glvalue访问对象的存储值,则行为未定义:[...]

     
      
  • 一种聚合或联合类型,其元素或非静态数据成员(递归包括子聚合或所包含的联合的元素或非静态数据成员)中包括上述类型之一,[...]
  •   

此句子是 strict-aliasing 规则的一部分。

是否允许我们通过类成员访问来别名?

class A{ //"casted to" aggregate
  int i;
  float g;
  };

int j=10;
int l = reinterpret_cast<A*>(&j)->i;

根据标准,仅当对象接受左值到右值转换 [conv.lval]/2时,才访问对象值。

[expr.ref]并没有规定 object-expression 必须引用该类型的对象,只是glvalue必须具有类类型( object-expression 是点“。”左侧的表达式。但是,在与成员访问相关的句子中经常出现一个单词,这可能意味着我忽略了该程序。例如[expr.ref]/4.1

  

如果E2是静态数据成员,并且E2的类型是T,则E1.E2是左值;表达式指定类的命名成员。

“指定”是否意味着该成员在其生存期内,并且我不能使用类成员访问perfom别名?还是[basic.lval] /11.6允许?

2 个答案:

答案 0 :(得分:0)

对于非静态数据成员,该词是:

  

如果E2是非静态数据成员,并且E1的类型为“ cq1 vq1 X”,而E2的类型为“ cq2 vq2 T”,则该表达式将指定对象的命名成员由第一个表达式指定。

很明显,*reinterpret_cast<A*>(&j)指定的对象,即j没有成员,所以行为是undefined by omission

答案 1 :(得分:-2)

编辑:与比我更了解的人进行了长时间交谈之后,得出的结论是:这是“行为”。

但是谁在乎呢?无论哪种方式,这都是可怕的做法。