完整对象被transparent replacement后,基类子对象成员访问的有效性判定
placement new透明替换对象后的成员访问合规性问题
struct A { int n; }; struct B : A {}; B foo; new (&foo) B { {42} }; // 新的B对象透明替换原foo int i = foo.n; // 是否合法?是否正确指向新B对象的A.n?
根据C++标准的[basic.life] p8条款,新构造的B对象会透明替换原对象foo。但新B的基类子对象A属于「潜在重叠子对象(potentially-overlapping subobject)」,无法被透明替换原foo.A。
核心问题:仅依靠外层B对象被透明替换这一点,是否足以保证foo.n的访问合法且正确指向新对象的成员?
目前存在两种解读:
解读1(符合标准规定):
根据[basic.life] p8的描述:[...] 原对象的名称将自动指代新对象 [...]
此时标识符foo已经指代新的B对象。再结合[expr.ref] p6.2关于成员访问表达式.的规则:
若E2是非静态数据成员[...] 表达式E1.E2指代第一个表达式所指向对象的对应成员子对象。
所以foo.n的解析逻辑是:先确定foo指向新的B对象,再访问该对象的n成员(即其基类A中的n),完全符合标准的字面规定。解读2(不符合标准规定):
该解读错误地将foo.n整个成员访问表达式视为[basic.life]中所说的「原对象的名称」,认为因为其所属的A子对象无法被透明替换,所以foo.n不能指代新的int成员。但标准中「原对象的名称」仅指直接关联原对象的标识符(也就是foo),而非成员访问表达式的整体,因此这一解读不符合标准的定义。
结论:第一种解读完全符合C++标准的规定,foo.n的访问是合法的,且正确引用了新B对象的A.n成员。
内容的提问来源于stack exchange,提问作者JMC
相关产品推荐
相关产品推荐

