C++ 删除应该什么都不做
c++ delete should do nothing
问题:
有没有办法让删除的行为像一个假人,即在调用时什么都不做?
为什么我需要答案:
我正在使用一个自定义内存池,当静态方法调用 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*/}
在具有重载的类中 new
使用 Pool::memory()
,但看起来这并没有解决问题。我使用一个简单的 std::cout 来查看调用的 cons/析构函数和重载的删除,例如:
void operator delete(void*) {std::cout << "deleting ClassName" << std::endl;}
所以在这样的代码中:
ClassName * instance = new ClassName();
instance->runMethod();
delete instance; //this is legacy code calling delete before the pool was developed
/*
other code goes here
*/
Pool::freeAllObjects(); // oops instance was already deleted
我得到以下输出:
constructing ClassName
<-- 构造函数调用
destructing ClassName
<-- 由于调用删除而调用析构函数
deleting ClassName
<-- 删除显示其消息
destructing ClassName
<-- 析构函数之所以调用,是因为 Pool::freeAllObjects 在对象上运行析构函数
编辑:抱歉,我没有提到要求是不使用智能指针,并且不允许将运算符删除设为私有(顺便说一下,我认为这是最好的选择(。
你不能阻止delete
调用析构函数;那就是它的作用。 但既然你抓住了operator 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;
}
然后,当您运行删除程序时,您可以检查标志。
或者甚至更好,在你的情况下;在你的operator delete
函数,只需取消注册对象的析构函数:添加Pool::memory()
返回的内容的clear_destructor
函数,并调用它。
operator delete
是一个释放函数。
删除表达式首先调用析构函数,然后调用相关的释放函数。
"Pool::memory((->save_destructor(( 只是保存一个指向运行泛型类型析构函数的函数的指针。相反,如果要共享释放责任,则使用 std::shared_ptr
在更高级别处理它(您可以将类限制为只能通过生成 std::shared_ptr
的函数实例化(。这就是std::shared_ptr
的目的。
由于分配器负责销毁对象,高低级关注点被混为一谈,这会导致复杂性和可能的错误。
将这些问题分开,例如通过使用std::shared_ptr
,你会得到一个更简单、更可靠的设计,这也将更符合C++语言中的这种分离。
Andrei Alexandrescu的经典著作"Modern C++ Design"详细讨论了如何实现自定义分配方案。很有可能您可以在洛基图书馆中找到该分配器。我相信它是开源的。
如果你想要一个类似Java的自动垃圾收集,那么你可以使用Boehm收集器。我知道有些人已经在大中型项目中成功地使用了它。但是,我没有直接经验,但请检查一下,如果这就是您的目标。
避免析构函数被自动调用,你必须实现placement new
运算符,在这种情况下,必须显式调用析构函数(请参阅C++常见问题解答(。
如果要通过delete
语句禁用释放内存,则重载它是一个好主意,无论是全局(如果您知道自己在做什么(还是每个类(可能使用继承(。 new
/delete
运算符是继承的(。
这完全取决于您要实现的目标以及您必须保持的与现有系统的兼容性。
无论哪种方式 - 都是可行的。另一个问题是 - 这是应该这样做的方式。
您可以考虑的另一种方法是禁用相关类的delete
。
只需使析构函数protected
或private
,然后将池分配器添加为friend
。
这强制执行了现有设计,而不是通过增加复杂性来支持不正确的使用(另一个答案(,或者将设计更改为更简单和干净的东西(我的另一个答案(。
- 当我从下面的代码中删除关键字 virtual 时,它可以正常工作,否则会出现错误。在这里"virtual"字的意义是什么?
- 如果我真的真的想从 STL 容器继承,并且我继承构造函数并删除新运算符,会发生什么?
- 我正在尝试使用 while 循环从字符串中删除字母,直到没有字母。我在这里做错了什么?
- 我什么时候会默认(而不是删除)基类中的复制和移动操作
- 删除对象(具有不同类型)的引用时会发生什么情况?
- 在析构函数中删除单链表的正确方法是什么?
- 处理从列表中删除指向对象的指针的"healthy"方法是什么?
- 将此私有删除器函数包装在结构中的目的是什么?
- 删除类成员的动态分配内存的最佳方法是什么
- 除了调用全局删除运算符之外,删除一个void指针还能做什么呢
- 在这种情况下,删除指针数组期间会发生什么?
- 为什么你会=删除隐式删除的默认构造函数,有什么意义?
- 当删除或删除[]被执行时,计算机会做什么?
- 如果在删除后使用 delete[] 会发生什么?
- 擦除remove_if成语 - 删除了什么吗?
- 如果我不删除动态创建的变量会发生什么
- 删除数组成员的更好方法是什么?
- 删除默认类构造函数有什么意义?
- 定义无删除指针的最干净方法是什么
- 使用动态指针数组进行动态对象分配 - 使用什么删除?