# [C++] !NULL and new 'no throw'

## Recommended Posts

fpsgamer    856
I have been doing some reading today, and I have a pair of questions: 1) First lets consider the following example:
int* p = (int*)malloc(sizeof(int));
if (!p) //NULL indicates a failure
{
cout<<"allocation failure!"
exit(1);
}


Embarrassingly my question deals with the '!p' expression. I have done this a million times, but now that I think about this check it no longer makes any sense to me. - If the allocation failed then ptr is equal to NULL. NOT NULL is equal to true. - But if the allocation was successful ptr is equal to some 'non-zero value'. NOT some 'non-zero value' yields another non-zero value (unless the value is equal to 0xFF). The resulting value will also be equal to true. How come if(!p) works? Shouldn't it be if(p == NULL) ? 2) Second question deals with the definition of new in the nothrow case. The following syntax will suppress any possible bad_alloc exception that new may throw and have new return 0 on error like malloc does:
char *p = new(nothrow) char;
char *p = new(nothrow) char[count];


These operators are defined like this (in header <new>):
namespace std {
// throwing operators:

// non-throwing operators
void* operator new(std::size_t size, const nothrow_t&) throw();
void* operator new[](std::size_t size, const nothrow_t&) throw();
}


I don't see how the usage matches the declaration. The definition seems to say that new is an operator that takes a size_t on the left and a const nothrow_t instance on the right. I suspect I am reading the operator definition incorrectly.

##### Share on other sites
Sneftel    1788
Quote:
 Original post by fpsgamerNOT some 'non-zero value' yields another non-zero value (unless the value is equal to 0xFF).

You're confusing logical NOT (!) with bitwise complement (~).

Quote:
 2) Second question deals with the definition of new in the nothrow case....I don't see how the usage matches the declaration.

operator-new signatures have a size_t as their first parameter, which is implicitly chosen as the sizeof the target type. This one has as its second parameter (aka the first placement parameter) a nothrow_t, a class with no member functions or variables, which exists only as a flag. "nothrow" is provided as a global variable of type nothrow_t.

##### Share on other sites
fpsgamer    856
Quote:
 Original post by Snefteloperator-new signatures have a size_t as their first parameter, which is implicitly chosen as the sizeof the target type. This one has as its second parameter (aka the first placement parameter) a nothrow_t, a class with no member functions or variables, which exists only as a flag. "nothrow" is provided as a global variable of type nothrow_t.

How does the first parameter get filled? ... I know you said it gets 'implicitly' filled, but does this mean that compiler treats 'new' as a special case? Or does the argument passing comply with conventional C++ argument passing.

##### Share on other sites
Spoonbender    1258
Quote:
 Original post by fpsgamerNOT some 'non-zero value' yields another non-zero value

Does it? [wink]
Have you tried it recently?

Quote:
 (unless the value is equal to 0xFF).

Not if you're doing a logical (as opposed to bitwise) not. The ! operator performs a logical not. It converts the value to a bool, and performs the not on that.
So !SomeNonZeroValue == false

Quote:
 How does the first parameter get filled? ... I know you said it gets 'implicitly' filled, but does this mean that compiler treats 'new' as a special case? Or does the argument passing comply with conventional C++ argument passing.]

You could say that. All operators have slightly different syntax. (when you do a + b, how does the "operator +(..., ...)" get its arguments filled in?)

As far as the compiler is concerned, overloaded operators are just function calls. They just have a different syntax in the source code, but that doesn't really change how it's compiled.

##### Share on other sites
Sneftel    1788
When you do new MyClass, operator new(sizeof(MyClass)) is executed.

##### Share on other sites
MaulingMonkey    1728
Quote:
 Original post by fpsgamer- If the allocation failed then ptr is equal to NULL. NOT NULL is equal to true.- But if the allocation was successful ptr is equal to some 'non-zero value'. NOT some 'non-zero value' yields another non-zero value (unless the value is equal to 0xFF). The resulting value will also be equal to true.How come if(!p) works? Shouldn't it be if(p == NULL) ?

As others have already said, !p is logical not -- it treats p as a simple boolean value, converting (for example) 0xBAADF00D to "true", and then taking the logical not of that (!true == false).

~p would be bitwise not, where the conversion to bool does not take place. I'm fairly confident that this operator isn't even defined for pointer types.

Quote:
 I don't see how the usage matches the declaration.

Simply put, it just doesn't. Operator new is one of those operators that is a serious WTF?!? moment of the C++ standard. Also nonsensical is the difference between pre-increment and post-increment operators:

class A {public:     void operator++()    {}     void operator++(int) {}};void f() {    A a;    ++a; // calls void A::operator++()    a++; // calls void A::operator++(int)}

Obviously, there's no actual new integer being passed in the post increment version, but the call still changes. With operator new([]), at least this invisible parameter out of nowhere has a somewhat sensible value.

##### Share on other sites
visitor    643
Quote:
 Quote: I don't see how the usage matches the declaration.Simply put, it just doesn't. Operator new is one of those operators that is a serious WTF?!? moment of the C++ standard.

But isn't it convenient that you don't have to pass sizeof(X) explicitly, as this is the value of the parameter that you want to pass anyway? (If you want more or less space for your type, you can use malloc.)

Another place where an argument is passed implicitly is the non-static member functions and the this pointer.

##### Share on other sites
Quote:
Original post by fpsgamer
Quote:
 Original post by Snefteloperator-new signatures have a size_t as their first parameter, which is implicitly chosen as the sizeof the target type. This one has as its second parameter (aka the first placement parameter) a nothrow_t, a class with no member functions or variables, which exists only as a flag. "nothrow" is provided as a global variable of type nothrow_t.

How does the first parameter get filled? ... I know you said it gets 'implicitly' filled, but does this mean that compiler treats 'new' as a special case? Or does the argument passing comply with conventional C++ argument passing.

operator new is not only an operator, it's also a keyword. As such, why can't one imagine a special treatment for this operator? And of course, there is a special treatment: where, in the code of operator new, do you call the class constructor? Why does Obj *o = new Obj() returns a pointer to an Obj instead of void*, despite the signature of operator new?

Using new is not as simple as calling a function. If it was one should call Obj *o = new(something,sizeof(Obj)), where something would be some type information (so that new would be able to call the constructor of Obj). This is quite convoluted with regard to the current syntax.

Now, the language allows you to override the way operator new allocates memory - this is done by creating an overload for the operator new() function. From an implementation point of view, the operator new() function overload has nothing to do with the call of new. They share the same name (for convenience), but they are different beasts.