Custom operator new, which returns a null pointer

I know that quite a few C ++ frequently asked questions (and the answers here are on SO) say that there is no need to check the return value of a simple new expression for null, since a simple new expression indicates errors, throwing exceptions. They basically claim that a simple new expression never returns null. (By "simple new expression" I mean a new expression that is not nothrow ).

However, despite the fact that it looked like a very simple question, I suddenly realized that I did not understand what specific assumptions they made (if any) when they gave this answer.

In particular, I am wondering if I can overload the basic form of the ::operator new form to always return a null pointer, and therefore expect all simple new expressions that use this operator to also return null pointers.

According to the language specification, if my ::operator new declared as low-key, then I can / should indicate a memory allocation error by returning a null pointer. So let's do just that

 void *operator new(size_t s) throw() { return 0; } int main() { int *i = new int; } 

In my experiments, the above new expression successfully returns a null pointer. So, am I breaking any rules in the above code or not? Is it legal to declare a simple ::operator new as non-throwing?

And if the above code is fine, then I would suggest that when someone claims that a simple new β€œnever returns a null pointer”, they do it under the assumption that the version ::operator new provided in the standard library was replaced by. Is this a presumption right?

+5
source share
1 answer

The operators you can replace are as follows

[replacement.functions]

 (2.1) β€” operator new(std::size_t) (2.2) β€” operator new(std::size_t, const std::nothrow_t&) (2.3) β€” operator new[](std::size_t) (2.4) β€” operator new[](std::size_t, const std::nothrow_t&) (2.5) β€” operator delete(void*) (2.6) β€” operator delete(void*, const std::nothrow_t&) 

void *operator new(size_t s) throw() invalid, it has to throw in case of error

[new.delete.single]

 void* operator new(std::size_t size); 

3 Required behavior: Return a non-zero pointer for a suitable alignment store (3.7.4), or throw a bad_alloc exception. This requirement is required to replace a version of this feature .

However, you can safely replace overloads with noexcept overloads with a function that always returns null, because whoever calls these overloads should be aware of this behavior and check the return value accordingly. Obviously, they will not be called if the nothrow tag is not passed, i.e. int* i = new (std::nothrow) int;

 void* operator new(std::size_t size, const std::nothrow_t&) noexcept; 

7 Required behavior: returns a non-null pointer to a suitable aligned store (3.7.4), or return a null pointer. This version of nothrow of operator new returns the pointer received, as if obtained from (possibly replacing) the regular version. This requirement is required for a replacement version of this feature.

+1
source

Source: https://habr.com/ru/post/1205742/


All Articles