C++のnew演算子は、失敗時にデフォルトでstd::balloc例外を投げますが、std::nothrowを指定することにより、失敗時にヌルが返ってくるようにできます:
#include <new> int main() { int* p = new(std::nothrow) int[3]; // 失敗時にヌルが返る if (p == nullptr) { ... } delete[] p; }
このnothrow版のnew演算子も、ほかの演算子と同様に置き換え可能になっています。そして、置き換え可能な演算子には、なぜかnothrow版のdeleteもあります:
void operator delete(void* ptr, const std::nothrow_t&) noexcept; void operator delete[](void* ptr, const std::nothrow_t&) noexcept;
これは一体何者なのでしょうか。通常の「delete p」もしくは「delete[ ] p」という呼び出しでは、これらの演算子は呼び出されず、throw可能なオーバーロードが呼び出されます。これを明示的に呼び出すには、以下のように「operator delete[ ](p, std::nothrow)」とする必要があります。
#include <iostream> #include <new> #include <cstdlib> void* operator new(std::size_t size, const std::nothrow_t&) noexcept { void* ptr = std::malloc(size); std::cout << "new:" << size << " " << ptr << std::endl; return ptr; } void operator delete[](void* ptr, const std::nothrow_t&) noexcept { std::cout << "free:" << ptr << std::endl; std::free(ptr); } int main() { int* p = new(std::nothrow) int[3]; operator delete[](p, std::nothrow); }
new:12 0x327d30 free:0x327d30
nothrow版のdeleteが呼び出されました。このdelete演算子は、標準ではthrowを許可するdelete演算子を呼び出すだけなので、動作に違いはありません。なので、この演算子は「ユーザーが置き換えて使用する場合に使い分けてもいい」ということを許可するためにあるようです。
https://twitter.com/kikairoya/statuses/266086241555054592
http://twitter.com/melponn/status/266086208680099841
http://twitter.com/melponn/status/266087356942143488
嘘書きました・・・。