I won't repeat the same things: it is undefined behavior, you should not do it... but provide a use case (which is a common idiom) that shows why it is sometimes interesting to allow the use of the variable there (in C):
int * p = malloc( 10 * sizeof *p );
If usage of p
in the right hand side was disallowed that would be a compiler error. You can circumvent it by explicitly stating the type in the rhs:
int * p = malloc( 10 * sizeof(int) );
But that is prone to subtle errors if at a later time the type is changed, as the compiler will not detect this case:
double * p = malloc( 10 * sizeof(int) ); // will compile and probably cause havoc later
Now, in C++ I can only assume that it is there for backwards compatibility. Note also, that some compilers will be able to detect that invalid use and trigger a warning from the more general group of uninitialized use of variable:
int i = i + 1;
// ^ uninitialized read
There are other situations, however, in C++ where you can pass a reference/pointer to uninitialized objects and it is perfectly fine. Consider:
template
struct NullObjectPattern { // intentionally out of order:
T* ptr;
T null;
NullObjectPattern() : ptr( &null ), null() {}
T& operator*() { return *ptr; }
T* operator->() { return ptr; }
};
While null
has not yet been initialized, using it in an expression that only takes it's address (but does not dereference it) is well defined: the memory location exists, it has been allocated and is present. The object itself has not been initialized, and as such dereferencing it will cause UB, but the fact that an uninitialized object is used in an expression does not mean that the code is actually wrong.