gpt4 book ai didi

c++ - C++11 中的 POD 和继承。 struct的地址是否==第一个成员的地址?

转载 作者:可可西里 更新时间:2023-11-01 18:11:08 28 4
gpt4 key购买 nike

(我已经编辑了这个问题以避免分心。在任何其他问题变得有意义之前,有一个核心问题需要被澄清。向那些现在回答似乎不太相关的人道歉。)

让我们设置一个具体的例子:

struct Base {
int i;
};

没有虚方法,也没有继承,一般是一个很笨很简单的对象。因此它是Plain Old Data (POD)它回到了可预测的布局。特别是:

Base b;
&b == reinterpret_cast<B*>&(b.i);

这是根据 Wikipedia (它本身声称引用了 C++03 标准):

A pointer to a POD-struct object, suitably converted using a reinterpret cast, points to its initial member and vice versa, implying that there is no padding at the beginning of a POD-struct.[8]

现在让我们考虑继承:

struct Derived : public Base {
};

同样,没有虚方法,没有虚继承,也没有多重继承。所以这也是POD。

问题:这个事实(Derived 是 C++11 中的 POD)是否允许我们说:

Derived d;
&d == reinterpret_cast<D*>&(d.i); // true on g++-4.6

如果这是真的,那么下面的定义是明确的:

Base *b = reinterpret_cast<Base*>(malloc(sizeof(Derived)));
free(b); // It will be freeing the same address, so this is OK

我不是在这里问newdelete - 考虑mallocfree 更容易。我只是好奇在像这样的简单情况下派生对象的布局规则,以及基类的初始非静态成员位于可预测位置的位置。

派生对象是否应该等同于:

struct Derived { // no inheritance
Base b; // it just contains it instead
};

事先没有填充?

最佳答案

您不关心 POD 性,您关心的是标准布局。这是来自标准第 9 节 [class] 的定义:

A standard-layout class is a class that:

  • 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.

然后保证您想要的属性(第 9.2 节 [class.mem]):

A pointer to a standard-layout struct object, suitably converted using a reinterpret_cast, points to its initial member (or if that member is a bit-field, then to the unit in which it resides) and vice versa.

这实际上比旧要求更好,因为 reinterpret_cast 的能力不会因添加非平凡的构造函数和/或析构函数而丢失。


现在让我们转到第二个问题。答案不是您所希望的。

Base *b = new Derived;
delete b;

是未定义的行为,除非 Base 具有虚拟析构函数。参见第 5.3.5 节([expr.delete])

In the first alternative (delete object), if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the static type shall have a virtual destructor or the behavior is undefined.


您之前使用 mallocfree 的片段大部分是正确的。这将起作用:

Base *b = new (malloc(sizeof(Derived))) Derived;
free(b);

因为指针 b 的值与从 placement new 返回的地址相同,而后者又与从 malloc 返回的地址相同。

关于c++ - C++11 中的 POD 和继承。 struct的地址是否==第一个成员的地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8864311/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com