我有以下代码,无法编译:
int *p = new(nothrow) int;
delete (nothrow) p; //Error
我得到的错误是:
错误C2440:'删除':无法从'const std :: nothrow_t'转换为'void *'
nothrow
版delete
是否存在?如果是这样,我该如何调用它?
在C ++:The Complete Reference中,它被认为存在,但我在网上看到了不同的意见,因此产生了混乱。
MSDN也谈到它的存在,但我找不到如何在代码中使用它。
Here,有些人说不存在这样的事情。
答案 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
不会抛出,因为:
使用nothrow
版本的new创建的项目将返回NULL而不是抛出bad_alloc异常。在NULL上使用delete
是完全有效的,因此不应该抛出它。
答案 2 :(得分:2)
对于大多数实际用途,只有一个版本的删除。 new(nothrow)
被编写为展示位置新运算符,但在大多数情况下,没有相应的删除版本。唯一的例外是当一个新的put抛出时调用的delete版本 - 但是因为(在这种情况下)你确信new
不能抛出,所以删除的版本是no真实使用/帮助。