42

Unlike new and delete expressions, std::malloc does not call the constructor when memory for an object is allocated. In that case, how must we create an object so that the constructor will also be called?

Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
ckv
  • 10,539
  • 20
  • 100
  • 144
  • possible duplicate of [Malloc function in C++](http://stackoverflow.com/questions/2740939/malloc-function-in-c) – sbi Jun 08 '10 at 06:42
  • 4
    Just for the record, I can see legitimate reasons why you wouldn't call new/delete. For example, you might need to allocate your objects from a special memory pool. – Edward Falk Apr 06 '18 at 19:04

8 Answers8

87

Er...use new? That's kind of the point. You can also call the constructor explicitly, but there's little reason to do it that way

Using new/delete normally:

A* a = new A();

delete a;

Calling the constructor/destructor explicitly ("placement new"):

A* a = (A*)malloc(sizeof(A));
new (a) A();

a->~A();
free(a);
Michael Mrozek
  • 169,610
  • 28
  • 168
  • 175
  • 18
    You should also mention that you need to call the destructor explicitly when using placement new, and not use 'delete' to destroy it. – Rudi Jun 08 '10 at 06:34
  • @MichaelMrozek I tried to do a->A(); the same way you called destructor, just to see if that works instead of doing new (a) A() to call constructor , but I get error : error: invalid use of 'A::A' .. is there any reason why this does not work, because it seemed more natural to me – solti Jul 17 '16 at 03:08
  • 1
    There are usecases. Lua, for example, only allows you to put individual metadata tables on "heavy" userdata, which means it has to allocate it and free it. It does, however, give you the ability to destruct it before it frees the memory. Since Lua uses malloc and free (it's in C), this definitely has a use-case. – Qix - MONICA WAS MISTREATED Jul 10 '17 at 05:36
  • Another use case that I can think of is object pooling. – Travis Vroman Apr 18 '20 at 01:55
  • 1
    This is still undefined behavior. You need to `std::launder` the `a` pointer, or you need to assign the result of the `new` expression to `a`. Otherwise the compiler is allowed to assume that the `a` pointer is still pointing to uninitialized memory; it isn't required to consider `new (a) A()` in its anlysis. – Jan Schultke Jun 11 '23 at 21:07
20

You can use "placement new" syntax to do that if you really, really need to:

MyClassName* foo = new(pointer) MyClassName();

where pointer is a pointer to an allocated memory location large enough to hold an instance of your object.

warrenm
  • 31,094
  • 6
  • 92
  • 116
  • 2
    `foo` and `pointer` may be of different types, or `pointer` may be an expression that calculates an offset into a larger block of memory. – warrenm Jun 08 '10 at 06:10
  • 3
    @RSamuel: I usually do it that way in the rare occasion I need placement new. I make sure I treat `pointer` as just memory and get an object through `new`. It also "hides" the cast. – GManNickG Jun 08 '10 at 06:15
  • @warrenm In the case where it is an offset into a memory block or the start of a memory block that was not allocated with malloc or new, it should be mentioned that pointer has to be properly aligned to hold the object. If it will not be aligned, accessing its primitive members (or the inner objects primitive members) may give a hardware exception on some hardware architectures and will result in slower access in other hardware architectures. – selalerer May 31 '12 at 17:15
6

Prefer new.

But if for some reason you have raw memory, you can construct it with "placement new":

new (ptr) TYPE(args);

And since you won't be using delete, you'll need to call the destructor directly:

ptr->~TYPE();
R Samuel Klatchko
  • 74,869
  • 16
  • 134
  • 187
4

Take a look at placement new operator, which constructs an object on a pre-allocated buffer.

Alex F
  • 42,307
  • 41
  • 144
  • 212
4

You mis-understand what malloc does. malloc does not create objects, it allocates memory. As it does not create objects there is no object for it to call a constructor to create.

If you need to dynamically create an object in C++ you need to use some form of new.

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
3

Use placement new. The advice is handy:

ADVICE: Don't use this "placement new" syntax unless you have to. Use it only when you really care that an object is placed at a particular location in memory. For example, when your hardware has a memory-mapped I/O timer device, and you want to place a Clock object at that memory location.

Igor Zevaka
  • 74,528
  • 26
  • 112
  • 128
3

The answer to this question has evolved over time, so here's an updated answer:

malloc merely allocates storage for an object. The following code works in C, but might not in C++:

T* object = (T*) malloc(sizeof(T));
*object = ...;

In C, writing to *object implicitly begins the lifetime of a T object, which is a special property of the memory allocated by malloc.

In C++, *object = would attempt to write to the object when its lifetime hasn't begun. This undefined behavior. However, if T is an implicit-lifetime type, this code is well-defined (since C++20):

[malloc, calloc, and realloc] implicitly create objects ([intro.object]) in the returned region of storage and return a pointer to a suitable created object. In the case of calloc and realloc, the objects are created before the storage is zeroed or copied, respectively.

- [c.malloc] §5

C++98 - C++17

Before C++20, the only legal solution would be to use placement-new:

auto object = reinterpret_cast<T>(std::malloc(sizeof(T));) // allocate storage
object = new (object) T(arg0, arg1, ...);                  // begin lifetime

do_something_with(*object);

object->~T();                                              // end lifetime
std::free(object);                                         // de-allocate storage

Pay attention to the fact that we are assigning the result of the new expression to object. If we didn't do that, the compiler would be allowed to assume that object is still pointing to unitialized memory from std::malloc! Accessing the object through object would be undefined behavior, or we would have to use std::launder.

C++20

C++20 has added two functions which are preferable to placement-new. They can be used at compile time, and they are used like regular functions:

auto object = reinterpret_cast<T>(std::malloc(sizeof(T));) // allocate storage
object = std::construct_at(object, arg0, arg1, ...);       // begin lifetime

do_something_with(*object);

std::destroy_at(object);                                   // end lifetime
std::free(object);                                         // de-allocate storage

Thanks to std::construct_at and std::destroy_at, we are no longer repeating the type T in three different places. It is deduced from the function arguments, which is much nicer.

Note: as explained above, we only need these functions if our type is not an implicit-lifetime type, e.g. when initializing std::string. The C code shown in the beginning is a working example of this, although you should prefer reinterpret_cast and std::malloc in C++.

C++23

std::malloc implicitly creates an object because it is treated specially by the standard. However, if we wanted to implement our own malloc function, we wouldn't benefit from this. C++23 introduces explicit lifetime management to solve this.

Always using std::construct_at is also not viable, because it value-initializes the storage, i.e. we can't create a buffer that remains uninitialized until written to.

The solution for implicit-lifetime types only in C++23 looks as follows:

auto object = reinterpret_cast<T>(my_malloc(sizeof(T));)      // allocate storage
object = std::start_lifetime_as<T>(object, arg0, arg1, ...);  // begin lifetime

do_something_with(*object);

// no need to explicitly end lifetime
my_free(object);                                              // de-allocate storage

Note: implicit-lifetime types are always trivially destructible, which is why we can omit std::destroy_at.

Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
-7
class A
{
    public:
      A() { printf("Constructor of A"); }
};

int main()
{
   A* pA = (A*) malloc(sizeof(A));  // Construtor is not going to be called.

   __asm { MOV EAX, pA}             // Makes pA as "this" pointer in intel based s/m.

   A();                             // Calling constructor explicitly.

   return 0;
}
  • 2
    Your "explicit constructor call" creates a temporary object, which is immediately destroyed. It does NOT construct an object at `pA`. – Ben Voigt Oct 11 '11 at 05:10
  • 1
    I have no idea if this works and I can't imagine when this would useful. The existing answers show how to do this using a documented language feature. – Blastfurnace Oct 11 '11 at 05:13