如何调用删除的nothrow版本?

时间:2010-10-23 19:02:43

标签: c++ memory-management

我有以下代码,无法编译:

int *p = new(nothrow) int;
delete (nothrow) p; //Error

我得到的错误是:

  

错误C2440:'删除':无法从'const std :: nothrow_t'转换为'void *'

nothrowdelete是否存在?如果是这样,我该如何调用它?


在C ++:The Complete Reference中,它被认为存在,但我在网上看到了不同的意见,因此产生了混乱。

MSDN也谈到它的存在,但我找不到如何在代码中使用它。

Here,有些人说不存在这样的事情。

3 个答案:

答案 0 :(得分:16)

存在std::nothrow_t解除分配函数,但您无法使用delete表达式调用它。

解除分配功能是为了完整性。如果new表达式因异常而失败,则编译器需要释放通过operator new分配的内存,并使用匹配调用operator delete。因此,需要operator delete接受std::nothrow_t,以允许此操作。

(通常情况下,new表达式new (args...) T将通过调用operator new(sizeof(T), args...)来分配内存。“匹配”表示调用operator delete使用相同的参数,除了第一个。)

请注意,您可以直接致电运营商:operator delete(memory, std::nothrow);。但是,delete表达式从不使用其他参数调用全局释放函数。


所以你可以用以下方式“召唤”它:

struct always_throw
{
    always_throw() { throw std::exception(); }
};

new (std::nothrow) always_throw;

在某些时候,这将通过调用:

来分配内存
void* __memory = operator new(sizeof(always_throw), std::nothrow);

由于对象的初始化抛出,编译器需要使用匹配的释放函数释放已分配的内存,因此它会:

operator delete(__memory, std::nothrow);

调用std::nothrow_t版本。

答案 1 :(得分:5)

没有delete的这种形式,因为delete不会抛出,因为:

  1. 不执行任何分配。
  2. 它经常用在不应该抛出的析构函数中!
  3. 使用nothrow版本的new创建的项目将返回NULL而不是抛出bad_alloc异常。在NULL上使用delete是完全有效的,因此不应该抛出它。

答案 2 :(得分:2)

对于大多数实际用途,只有一个版本的删除。 new(nothrow)被编写为展示位置新运算符,但在大多数情况下,没有相应的删除版本。唯一的例外是当一个新的put抛出时调用的delete版本 - 但是因为(在这种情况下)你确信new不能抛出,所以删除的版本是no真实使用/帮助。