gpt4 book ai didi

c++ - 重载删除运算符以删除库中分配的内容

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:52:23 25 4
gpt4 key购买 nike

我正在使用具有类 Register 的框架,我可以在其中注册 A 的实例。

Register r;
A * a1 = new A();
r->register(a1);
A * a2 = new A();
r->register(a2);

Register 将取得所有权并在超出范围时删除所有已注册的 A

我想修改共享库中的 A 行为(在我的例子中是这样),所以,我将做这样的事情(在库中):

class B : public A {
...
}

B * get_customized_a() {
return new B();
}

然后在主程序中

Register r;
A * a1 = get_customized_a();
r->register(a1);

但是现在 a1 将在主程序中被删除,而不是在库中!据我了解,这是一个很大的禁忌。

那么如何解决呢?


我想出了两个解决方案:

1)使用A,通过单机函数自定义

在插件中:

void customize_a(A * a) { ... }

在主程序中:

Register r;
A * a1 = new A();
customize_a(a1);
r->register(a1);

我必须说我不太喜欢它:/

2) B 类重载删除运算符

在插件中

class B : public A {
...
static void operator delete(void * ptr) {
::operator delete(ptr);
}
}

在主程序中:

Register r;
A * a1 = get_customized_a();
r->register(a1);

但是,我之前从未重载过operator delete,所以我不确定这是否会起作用(如预期的那样)。

3) 我错过了什么方法吗?有更好的解决方案吗?

谢谢大家

最佳答案

如果您使用指向其中一个基类的指针删除一个类,那么无论对象创建和销毁的位置如何,析构函数在基类中都必须是虚拟的。模块边界与此无关。

另一方面,如果一个对象的构造和销毁发生在不同的模块中,那么只有当这些模块的 new 和 delete 运算符从不同的池中分配/释放内存时,才会出现问题。例如,如果这些模块链接到不同版本的运行时库,就会出现这种情况。类似的情况是当您显式覆盖库中的 new 和 delete 运算符并从不同的池中自己进行分配时,这些模块的分配器代码之间没有协作。在这种情况下,虚拟析构函数不会将您从问题中解救出来,因为对象的构造使用一个模块的分配器/池分配内存,并且您调用另一个模块的 delete 运算符,该模块试图从完全不同的对象中释放对象水池。结果通常是错误的“堆损坏”运行时错误或类似错误。

如果您曾经遇到过上述问题,那么正确的解决方案是在基类中同时引入虚拟析构函数和虚拟 Release() 方法。 Release() 方法应该删除带有丑陋的delete this; 的对象。当您将构造的对象传递给外部模块时,它必须通过调用 Release() 方法来删​​除对象,而不是直接删除它,这样 Release()方法使用拥有类和实例的模块的删除运算符删除对象。通常这种技术与智能指针相结合,以便外部模块使用智能指针引用此类对象,通过调用 Release() 方法自动删除对象。

关于c++ - 重载删除运算符以删除库中分配的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26196019/

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