gpt4 book ai didi

c++ - 使用 placement new 延迟真正的基类构造

转载 作者:行者123 更新时间:2023-11-30 02:07:20 27 4
gpt4 key购买 nike

我想问的是以下方法是否(以及为什么)a) 合法和 b) 道德。我问的重点是 C++03,但也欢迎关于 C++11 的注释。这个想法是为了防止本身可以默认构造的派生类实现愚蠢的 B::B(int foo) : A(foo) {} 构造函数。

class Base {
private:
int i;
Base(int i) : i(i) {}
protected:
Base() {}
public:
static Base* create(int i);
};
class Derived : public Base {
};

Base* Base::create(int i) {
Derived* d = new Derived();
Base* b = static_cast<Base*>(d);
delete b;
new(b) Base(i);
return d;
}

我的直觉告诉我,这里有些可疑。如果任何 Derived 类在其构造函数中访问 Base 成员,我想在其他地方,但否则我很难找到该方法不好的正当理由。

无论如何,如果您认为这是一种可接受的方法,将如何处理引用成员(类似于 int& Base::j)?

注意:这是 How can I fake constructor inheritance in C++03? 的后续问题.


编辑:发布问题时我一定是分心了。当然,我的意思不是 delete b,而是 b->~Base()。我怪低血糖!

最佳答案

代码不正确并触发未定义的行为。您的 Base 类没有虚拟析构函数,这意味着 delete b 将导致未定义的行为。

UB 在调用delete 时的原因包括它不会释放 派生资源(这似乎是代码的目的,哎哟!),事实上它会尝试释放分配的内存,这可能有效或无效,具体取决于两个对象的布局。如果它未能释放内存,它可能会崩溃,如果成功,则在下一行中放置新调用将尝试初始化内存中已释放的对象...

即使您将代码(试图避免释放问题)更改为:

Base* Base::create(int i) {
Derived *d = new Derived;
Base * b = static_cast<Base*>(d);
b->~Base(); // destruct, do not deallocate
new (b) Base(i);
return d;
}

如果没有delete,因此未定义行为的那个特定源已经消失,代码仍然是未定义行为(可能有太多的方式甚至无法提及)。一旦对析构函数的调用仍然是 UB,即使不是,您重新创建 Base 类型的事实意味着该对象的动态调度可能会将对象视为 Base 而不是 Derived 对象(在 vtable 的情况下,指向 RunTime Type 信息的 vptr 将引用到 Base,而不是 Derived)

而且可能还有两三件事可能会出错,我现在想不起来...

关于c++ - 使用 placement new 延迟真正的基类构造,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7996923/

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