Why Is the New Operator Allowed to Return *Void to Every Pointer-Type

Why is the new operator allowed to return *void to every pointer-type?

You have confused the new operator and the operator new function. No problem, everybody does. They are almost the same, except that they are different.

The function void* operator new(size_t) grabs a block of raw, untyped memory from whatever tree it grows on, and returns it to the program.

void* raw_memory = ::operator new(42);

It is an ordinary function with somewhat weird name.

The new operator is not a function and not a function call. It's a separate language construct. It takes raw memory (normally, one returned by the void* operator new(size_t) function) and turns it into an object by calling a constructor. It then returns a properly typed pointer to the newly-created object.

Fish* f = new Fish;

UPDATE Naturally, there is also the delete operator (the opposite of the new operator) and the void operator delete(void*) function (the opposite of the void* operator new(size_t) function).

There are also the new[] operator, the delete[] operator, the void* operator new[](size_t) function, and the void operator delete[](void*) function; they deal with arrays of objects (as opposed to individual objects).

There are also so-called "placement new" forms that do not call any of the operator new functions for fresh memory, but instead require an explicit pointer to raw memory. They have no corresponding built-in "delete" forms. You can roll your own if you are so inclined, but I refuse to talk about any of this while being sober.

How come a new-expression can correctly produce the pointer type, even though it should return void*?

It's easy to confuse the new keyword with the operator new, but they're two different things. When you write a memory allocation function, its name is operator new and it does, as you say, return void*. But you don't ordinarily call that operator directly; instead, you create a new object with the new keyword. The compiler understands that keyword; it calls operator new to get memory for the object (or objects, for array new) that's being created and does whatever initialization is appropriate. The type of the result of that expression is a pointer to the type being created.

So, in the code

auto x = new int{};

the type of the expression new int{} is int*, so the deduced type for x is also int*.

Does new return (void *) in C++?

You are confusing operator new (which does return void*) and the new operator (which returns a fully-typed pointer).

void* vptr = operator new(10); // allocates 10 bytes
int* iptr = new int(10); // allocate 1 int, and initializes it to 10

Why doesn't new require a cast to the pointer even though malloc requires it?

Because when you're using new, you (normally) use a "new expression", which allocates and initializes an object. You're then assigning the address of that object to a pointer to an object of the same (or parent) type, which doesn't require a cast. A normal new expression (i.e., not a placement new) will invoke operator new internally but the result of the new expression is not just the result from operator new.

If you invoke operator new directly, then you need to cast its result to assign the return value to a non-void pointer, just like you have to do with the return from malloc.

Why any type can be assigned void* but I can not return void* for any type function?

void is an incomplete type; it does not specify an integer type, a floating-point type, a structure type, or any other specific type. It is largely a placeholder.

void * is a pointer to void. By pointing to void, we leave it open what a pointer points to. So a void * could be an address that was derived from an int, from structure, or from any other object type.

So void * is not an incomplete type. It is some sort of pointer type.

When a void * is assigned to an int *, the C standard says an implicit conversion is done, because a void * could be pointing to an int.

Note that void * and int * are significantly different types. void * could be pointing to any object type, but int * should point to an int. The C standard even allows a void * and an int * to have different sizes.

In turn, this means that pointing to a void * and pointing to an int * are different. So, when a void ** is assigned to an int *, this violates a constraint in the C standard. The void ** should be pointing to a void *. The void ** should not be pointing to an int *.



Related Topics



Leave a reply



Submit