C++ c++;删除不应该做任何事情

C++ c++;删除不应该做任何事情,c++,memory-management,operator-overloading,C++,Memory Management,Operator Overloading,问题: 是否有任何方法可以使delete像一个伪对象一样工作,即在调用时不执行任何操作 为什么我需要答案: 我使用的是一个自定义内存池,当调用静态方法时,它会将所有对象从内存中释放出来。pool::freeAllObjects() 所有类都有一个重载运算符new,如下所示: void * operator new (size_t size) { void * obj = Pool::memory()->allocate(size); Pool::memory()->save_dest

问题:

是否有任何方法可以使delete像一个伪对象一样工作,即在调用时不执行任何操作

为什么我需要答案:

我使用的是一个自定义内存池,当调用静态方法时,它会将所有对象从内存中释放出来。
pool::freeAllObjects()

所有类都有一个重载运算符new,如下所示:

void * operator new (size_t size)
{
void * obj = Pool::memory()->allocate(size);
Pool::memory()->save_destructor((ClassName*)obj);
return obj;
}
Pool::memory()->save_destructor()
只保存指向运行泛型类型析构函数的函数的指针

如果没有人对使用池创建的对象调用
delete
,那么一切都会正常运行,但在我们想要使用的代码中,有许多对象的实例调用了
delete
,因此为了向后兼容,我尝试像这样进行重载
delete

void operator delete(void*) {/*do nothing*/}
使用
Pool::memory()
,但这似乎并没有解决问题。我使用一个简单的std::cout来查看调用的cons/destructor和重载的delete,如:

void operator delete(void*) {std::cout << "deleting ClassName" << std::endl;}
我得到以下输出:


构造类名
运算符删除
是一个释放函数

delete表达式首先调用析构函数,然后调用相关的释放函数

“Pool::memory()->save_destructor()只保存指向运行泛型类型析构函数的函数的指针。”这是一种不好的设计。相反,如果要共享解除分配责任,则使用
std::shared\u ptr
(您可以将类限制为只能通过生成
std::shared\u ptr
的函数实例化)。这就是
std::shared_ptr
的用途

由于分配器负责销毁对象,高级别和低级别的关注点被混为一谈,这会导致复杂性和可能的bug

使用了 STD::SyrdYPPTR ,可以得到更简单、更可靠的设计,这也将更符合C++语言中的这种分离。


Andrei Alexandrescu的经典著作《现代C++设计》详细讨论了如何实现自定义分配方案。您可能会在Loki库中找到该分配器。我相信它是开源的



如果您想要一个类似Java的自动垃圾收集,那么您可以使用Boehm收集器。我知道有些人已经在大中型项目中成功地使用了它。然而,我没有直接的经验,但请检查一下这是否是你的目标。

你不能阻止
删除
调用析构函数;那是
它的作用。但是由于您正在捕获
操作符delete
函数,您可以使用某种隐藏的 旗帜比如:

union MemoryHeader
{
    bool hasBeenDeleted;
    double forAlignment;
};

void* operator new ( size_t size )
{
    MemoryHeader* hdr = static_cast<MemoryHeader*>(
                Pool::memory()->allocate( size + sizeof( MemoryHeader ) ) );
    hdr->hasBeenDeleted = false;
    void* obj = hdr + 1;
    Pool::memory()->save_destructor( (ClassName*)hdr );
    return obj;
}

void operator delete( void* obj )
{
    MemoryHeader* hdr = static_cast<MemoryHeader*>( obj ) - 1;
    hdr->hasBeenDeleted = true;
}
union MemoryHeader
{
布尔已经被删除;
双孔排列;
};
void*运算符新(大小\u t大小)
{
MemoryHeader*hdr=静态(
Pool::memory()->allocate(size+sizeof(MemoryHeader));
hdr->hasBeenDeleted=false;
void*obj=hdr+1;
Pool::memory()->save_析构函数((ClassName*)hdr);
返回obj;
}
void运算符删除(void*obj)
{
MemoryHeader*hdr=静态(obj)-1;
hdr->hasBeenDeleted=真;
}
然后,当运行删除程序时,可以检查标志

对你来说,也许更好;在您的
操作员中删除

函数,只需取消注册对象的析构函数:add
clear\u destructor
函数返回
Pool::memory(),

并调用它。

如果要避免自动调用析构函数,必须实现
placement new
运算符,在这种情况下,必须显式调用析构函数(请参阅)

如果您想通过
delete
语句禁用释放内存,那么重载它是一个好主意,可以是全局(如果您知道自己在做什么)或每个类(可以使用继承。
new
/
delete
运算符是继承的)

这完全取决于您想要实现什么,以及您必须保持与现有系统的兼容性


无论哪种方式,都是可以做到的。另一个问题是,应该这样做。

< P>您可以考虑的是禁用相关类的<代码>删除< /代码>。< /P> 只需将析构函数
设置为protected
private
,并将池分配器添加为
友元


这加强了现有的设计,而不是通过增加复杂性来支持不正确的使用(另一个答案),或者将设计更改为更简单和干净的设计(我的另一个答案)。

使用delete时,无法阻止调用析构函数。您可以修改
运算符删除
,但删除过程分为两步:调用对象的析构函数,然后调用
运算符删除
。您可以将
unique\u ptr
/
shared\u ptr
与一个自定义删除程序一起使用,该删除程序实际上并不调用delete,也从不处理原始指针或显式调用delete。为什么要在
void*obj=hdr+1
然后在删除时减去它,为什么不干脆
void*obj=hdr相反?为了说明MemoryHeader使用的空间。@jhofman0x为什么要添加+1而不是+2、+3或其他东西?为什么需要这样做?如果删除了+1/-1,会发生什么情况?+1/-1偏移了MemoryHeader的大小,因为它们被添加到MemoryHeader*中,指针算法就是这样工作的。在+1的情况下,他有一个MemoryHeader*,他想得到对象的地址。在-1的情况下,他有对象的地址,他想得到MemoryHeader*。这是假设在为对象分配的每个内存块之前都有一个MemoryHeader。这可能是他真正应该做的。让他的系统正常工作
union MemoryHeader
{
    bool hasBeenDeleted;
    double forAlignment;
};

void* operator new ( size_t size )
{
    MemoryHeader* hdr = static_cast<MemoryHeader*>(
                Pool::memory()->allocate( size + sizeof( MemoryHeader ) ) );
    hdr->hasBeenDeleted = false;
    void* obj = hdr + 1;
    Pool::memory()->save_destructor( (ClassName*)hdr );
    return obj;
}

void operator delete( void* obj )
{
    MemoryHeader* hdr = static_cast<MemoryHeader*>( obj ) - 1;
    hdr->hasBeenDeleted = true;
}