Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I invoke the nothrow version of delete?

I have the following code, which doesn't compile:

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

The error I get is:

error C2440: 'delete' : cannot convert from 'const std::nothrow_t' to 'void*'

Does a nothrow version of delete exist? If so, how can I invoke it?


In C++: The Complete Reference, it's given that it exists but I saw different opinions online, hence the confusion.

MSDN also talks about its existence, but I couldn't find how it can be used in code.

Here, some people are saying that there is no such thing.

like image 301
bjskishore123 Avatar asked Oct 23 '10 19:10

bjskishore123


People also ask

What is Nothrow keyword used for?

The nothrow object is used in placement new expressions to request that the new operator return a null pointer instead of throwing bad_alloc if the memory allocation request cannot be fulfilled. The nothrow_t type does not do anything; it is used only in overloaded placement new and delete operators.


1 Answers

A std::nothrow_t deallocation function exists, but you cannot call it with a delete expression.

The deallocation function is there for completeness. If a new expression fails because of an exception, the compiler needs to free the memory it allocated via operator new with a matching call to operator delete. So there needs to be an operator delete that accepts a std::nothrow_t, to allow this.

(That is, in general, a new expression with the form new (args...) T will allocate memory with a call to operator new(sizeof(T), args...). To "match" means to call operator delete with the same arguments, except the first.)

Note you can call the operator directly: operator delete(memory, std::nothrow);. However, a delete expression never calls a global deallocation function with additional parameters.


So you can "call" it with:

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

new (std::nothrow) always_throw;

At some point, this will allocate memory with a call to:

void* __memory = operator new(sizeof(always_throw), std::nothrow);

Since the initialization of the object throws, the compiler needs to free the allocated memory with a matching deallocation function, so it does:

operator delete(__memory, std::nothrow);

Calling the std::nothrow_t version.

like image 195
GManNickG Avatar answered Oct 16 '22 18:10

GManNickG