在此放置新位置

Placement new on this

本文关键字:位置 新位置      更新时间:2023-10-16

我看到了这样的代码:

class BaseClass
{
public:
    BaseClass(int param);
};
class Derived: public BaseClass
{
};
BaseClass::BaseClass(int param)
{
    new (this) Derived;
}

代码试图做什么?我认为它会创建一个派生的类对象。然而,背后的逻辑是什么?我认为当我们调用新的 BaseClass(( 时,它只会根据基类大小分配内存。但是,为什么我们仍然可以将此指针传递给新位置以构造派生类对象?

编辑:感谢您的回复。在进一步检查时,代码确实覆盖了基类的运算符 new,以分配足够的内存来容纳派生类对象,并避免递归调用它,在派生类构造函数中,它调用了另一个基类构造函数。

基本上我认为它正在尝试创建类似工厂的东西,其中创建的对象取决于参数。根据答复,这样做似乎不是一个好的做法。

出于大约六个原因,这是可怕的未定义的行为。永远不要,永远不要这样做。

这会在this指向的内存上调用 DerivedClass 的构造函数。因此,new运算符不会分配任何内容,它只是调用构造函数来初始化已分配的内存中的对象。

然而,在这种特殊情况下,结果充其量是非常奇怪的。您实际上是使用派生类的构造函数初始化基类的对象。结果是你仍然拥有基类的对象,但具有派生类的状态,或者至少假装具有这样的状态。根据派生类是否引入了其构造函数引用的一些新字段,这甚至可能导致内存访问冲突......

所以,简短的建议:不要那样做。一般来说,除非你真的知道自己在做什么,否则根本不要使用 PLACEMENT NEW

该代码中有很多错误。对于初学者来说,为了选择微不足道的那个,构造函数不应该在类声明中限定。

接下来的事情是它看起来正在做什么:看起来它正在为Base分配的内存中创建 Derived 类型的对象。

  • 这里的问题包括Derived可能需要比Base更多的内存,并且不能保证内存可用。
  • 它将触发一个无限递归循环,因为Base的构造函数正在尝试创建一个Derived,而又会尝试调用Base的构造函数,这将尝试创建一个Derived...
  • 即使递归被切断(提供构造函数的替代Base,并将调用的Derived构造函数调度到该非重复版本(,并且Derived适合Base的内存占用,任何已经初始化的Base成员都将被重新初始化,调用未定义的行为。例如,如果Base包含内部分配和管理内存的属性,则其构造函数将被调用两次,从而泄漏在第一次调用中获取的资源。分别,构建和破坏的对象数量不匹配。
  • 可能还有许多其他问题,直到 DeadMG 提到的六个百亿数。

这是未定义的行为,它可能会递归调用基类构造函数,你会得到无限递归。

您的代码无法编译。

没有为Derived定义构造函数,编译器无法生成默认构造函数Base因为它只有一个需要参数的构造函数。

我认为这背后没有逻辑。顺便说一下,在C++构建派生实例时,对象首先初始化为 base(即首先执行 base 的构造函数(。因此,我会说这段代码将永远递归地调用自身(直到堆栈空间耗尽(。