c ++ delete应该什么也不做 [英] c++ delete should do nothing

查看:202
本文介绍了c ++ delete应该什么也不做的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题:



有什么办法使删除的行为像一个虚拟,即在调用时什么也不做?



为什么我需要答案:



我使用一个自定义内存池,当调用静态方法时释放所有对象从内存中 Pool :: freeAllObjects()



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

  void * operator new(size_t size)
{
void * obj = Pool :: memory ;
Pool :: memory() - > save_destructor((ClassName *)obj);
return obj;
}

Pool :: memory() - > save_destructor ()只是保存一个指向运行一个泛型类型析构函数的函数的指针。



如果没有人调用 delete 在使用池创建的对象,然后一切正常,但在代码中,我们要使用它有许多对象的实例 delete

$

  void operator delete(void *){/ * do nothing * /} 

使用 Pool :: memory()
重载 new 的类,没有解决问题。我使用一个简单的std :: cout看到cons / destructor调用和重载删除像:

  void operator delete *){std :: cout<< 删除ClassName< std :: endl;} 

所以在这样的代码:

  ClassName * instance = new ClassName() 
instance-> runMethod();
delete instance; //这是在池开发之前调用delete的旧代码
/ *
其他代码在这里
* /
Pool :: freeAllObjects(); // oops instance was already deleted

我得到以下输出:



构造ClassName < - 构造函数



ClassName < - 析构函数因为调用delete而被调用



删除ClassName - 删除显示其消息



销毁ClassName < - 析构函数,因为Pool :: freeAllObjects正在运行对象上的析构函数



编辑:
对不起,我没有提到要求不是使用智能指针和使操作符删除私有

解决方案

您不能阻止 delete 调用析构函数;这是
它做什么。但是由于你捕获了稍后调用的运算符delete
函数,你可以使用某种隐藏的
标志。像:

  union MemoryHeader 
{
bool hasBeenDeleted;
double forAlignment;
};

void * operator new(size_t size)
{
MemoryHeader * hdr = static_cast< MemoryHeader *>(
Pool :: memory (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)
hdr-> hasBeenDeleted = true;
}

然后,当您运行删除程序时, p>

或许更好,在你的情况下;在运算符中删除
函数,只需注销对象的析构函数:add
a clear_destructor 函数到 Pool :: memory()返回,
并调用。


Question:

is there any way to make delete behave like a dummy i.e do nothing when called?

Why I need the answer:

I'm using a custom memory pool that frees the all the object from memory when a static method is called Pool::freeAllObjects().

all the classes have an overloaded operator new like the following:

void * operator new (size_t size)
{
void * obj = Pool::memory()->allocate(size);
Pool::memory()->save_destructor((ClassName*)obj);
return obj;
}

Pool::memory()->save_destructor() just saves a pointer to function that runs the destructor of a generic type.

if no one calls delete on the objects that are created with the pool then everything behaves correctly but in the code we want to use it there are many instances of objects which have delete called on, so for backward compatibility I tried to make an overloaded delete like this

void operator delete(void*) {/*do nothing*/}

in the classes that have the overloaded new using the Pool::memory() , but it looks like that did not solve the problem. I used a simple std::cout to see the cons/destructor called and an overloaded delete like:

void operator delete(void*) {std::cout << "deleting ClassName" << std::endl;}

so in a code like this:

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

I get the following output:

constructing ClassName <-- constructor called

destructing ClassName <-- destructor called because of calling delete

deleting ClassName <-- delete displaying its message

destructing ClassName <-- destructor called because of the Pool::freeAllObjects running the destructor on the object

EDIT: sorry that I didn't mention that the requirement was not to use smart pointers and making operator delete private (which I think is the best option by the way) is also not allowed.

解决方案

You can't prevent delete from calling the destructor; that's what it does. But since you're catching the operator delete function which is called later, you can use some sort of hidden flag. Something like:

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;
}

Then, when you run your deleters, you can check the flag.

Or perhaps even better, in your case; in your operator delete function, just deregister the destructor for the object: add a clear_destructor function to what Pool::memory() returns, and call it.

这篇关于c ++ delete应该什么也不做的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆