在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允许?
答案 0 :(得分:0)
对于非静态数据成员,该词是:
如果E2是非静态数据成员,并且E1的类型为“ cq1 vq1 X”,而E2的类型为“ cq2 vq2 T”,则该表达式将指定对象的命名成员由第一个表达式指定。
很明显,*reinterpret_cast<A*>(&j)
指定的对象,即j
没有成员,所以行为是undefined by omission。
答案 1 :(得分:-2)
编辑:与比我更了解的人进行了长时间交谈之后,得出的结论是:这是“行为”。
但是谁在乎呢?无论哪种方式,这都是可怕的做法。