The definitions of three classes are as follows:
三个类别的定义如下:
class A { };
class B { A a; };
class C : public A { B b; };
According to the definition of a standard-layout class in C++11:
根据C++11中标准布局类的定义:
- has no non-static data members of type non-standard-layout class (or array of such types) or reference
- has no virtual functions (10.3) and no virtual base classes (10.1),
- has the same access control (Clause 11) for all non-static data members,
- has no non-standard-layout base classes,
- either has no non-static data members in the most derived class and at most one base class with non-static data members, or has no base classes with non-static data members, and
- has no base classes of the same type as the first non-static data member
Classes A and B are clearly standard-layout classes. The issue arises with class C, which doesn't appear to violate any of the standard-layout class definitions, yet it is still defined as a non-standard-layout class. Does class C violate any specific rule?
A类和B类显然是标准布局类。问题出现在类C上,它似乎没有违反任何标准布局类定义,但它仍然被定义为非标准布局类。C类是否违反了任何特定的规则?
I used the Clang compiler for testing.
我使用Clang编译器进行测试。
更多回答
GCC says standard-layout, MSVC and Clang say not: godbolt.org/z/1M9M5j8Yc
GCC说标准布局,MSVC和Clang说不:gobolt.org/z/1M9M5j8Yc
I believe it's a defect. The footnote for bullet 6 says "This ensures that two subobjects that have the same class type and that belong to the same most derived object are not allocated at the same address" - but it doesn't actually ensure that; this is exactly what happens in your example. For this reason, the definition in C++17 is more elaborate, and in particular looks at the members of the type of the first data member (and at their members, recursively).
我认为这是一个缺陷。项目符号6的脚注说“这确保了具有相同类类型并且属于相同派生最多的对象的两个子对象不会分配到相同的地址”--但它实际上并没有确保这一点;这正是在您的示例中发生的事情。因此,C++17中的定义更加详细,尤其是第一个数据成员的类型的成员(以及它们的成员,递归地)。
@IgorTandetnik It is certainly a defect. There is a normative equivalent of that note in [intro.object] that conflicts with the standard-layout definition when taken together with the rules for pointer-interconvertibility requiring same addresses. It is CWG 2736. I guess the question is here why the compilers decide to resolve this conflict one way or the other, in particular when the rules for standard-layout types (even if conflicting with something else) are pretty clearly written.
@伊戈尔坦德尼克,这当然是一个缺陷。在[Intro.Object]中有一个与该注释相同的规范等价物,当与需要相同地址的指针可互换性规则结合在一起时,该注释与标准布局定义冲突。是CWG2736。我想这里的问题是,为什么编译器决定以这样或那样的方式解决这个冲突,特别是在标准布局类型的规则(即使与其他内容冲突)写得相当清楚的情况下。
It might have something to do with different interpretations of 6
. That C
is an A
and the first data member is also kind of an A
(First member in B
).
这可能与对6的不同解释有关。C是A,第一个数据成员也是A(B中的第一个成员)。
我是一名优秀的程序员,十分优秀!