3

In C, it is considered poor form to typecast the result of a call to malloc. However, it seems that the result of calls to malloc in C++ should be typecast, even though both malloc and new have return type void* and calls to new are not typecast. Is there a reason why in C++ the void pointer returned by new is automatically promoted while the void pointer returned by malloc isn't?

Community
  • 1
  • 1
asnr
  • 1,692
  • 1
  • 14
  • 17
  • I think it is because `new` is a keyword, but `malloc()` is not a keyword, I don't know surely. +1 vote – Govind Balaji Feb 16 '13 at 13:24
  • 1
    Part of your confusion (btw, it is _must_ cast, not _should_ for C++) comes from the fact that C is much more lax about pointer types. It is allowable (and indeed well-defined) to assing `void*` to any pointer type. In C++, you would consider this approach "broken", because they are pointers of different types, so it isn't meaningful to assign one to the other. Though, funnily, C++ explicitly allows for that exact same invalid conversion from no-type to some-type with the zero literal and with `nullptr`. – Damon Feb 16 '13 at 13:53

2 Answers2

14

You are confusing operator new with the new operator. operator new just allocates raw memory and returns a void*, whereas new T also calls the constructor after allocation and returns a T*.

Also, you have to cast the result of malloc in C++, because unlike C, C++ does not allow implicit conversions from void* to other pointer types. Note that void* is used very rarely in C++.

fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • 1
    "*Note that `void*` is used very rarely in C++.*" That ought to be "should be", not "is". I've seen highly unpleasant amounts of `void*` use in C++ code. – Nicol Bolas Feb 16 '13 at 13:43
5

In C++, memory locations are indeed expressed through void pointers. But memory isn't the same as objects. An object needs memory in order to live, but the object is distinct from the memory in which it resides.

You need to create an object in the memory. If you will, the new-operator "converts" between memory and objects:

#include <cstdlib>

void * pm = std::malloc(sizeof(int));       // C-style
void * qm = ::operator new(sizeof(int));    // C++-style

int * po = ::new (pm) int(10);              // void pointer goes in...
int * qo = ::new (qm) int(20);              // ...object pointer comes out.

// (... class-type objects would need to be destroyed...)

std::free(pm);
::operator delete(qm);
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084