1

Here is a class.

class A
{
public:
A()
private:
int m_a;
};

Can we create an object of a class instead placement operator new and using malloc, like this:

void* a = malloc(sizeof(A)); // allocate raw memory 
A* obj = reinterpret_cast< A* > ( a ); // assign to the adress
a->A() // call the constructor

Is it correct? If not, can we construct an object using malloc and instead placement new (using some other C techniques)?

Emil Laine
  • 41,598
  • 9
  • 101
  • 157

3 Answers3

4

You'll need to use placement new after getting the raw memory from malloc.

class S
{};
...
void *mem = malloc(sizeof(S));
S* s = new (mem) S(); //this is the so called "placement new"

Then explicitly call its destructor.

s->~S();
free(mem);
2

Lets clear up the terminology a bit. 'Placement new' is the means of invoking the constructor only, it does not allocate memory. Regular new is more analogous to malloc because it allocates memory.

The proper way to use malloc in C++ is to malloc and then use placement new.

void* a = malloc(sizeof(A)); // allocate raw memory 
A* obj = reinterpret_cast< A* > (a);
new(obj) A(); // placement new syntax runs the constructor of A()

Or further simplified:

void* a = malloc(sizeof(A)); // allocate raw memory 
A* obj = new(a) A(); // placement new syntax runs the constructor of A()

However, there is (typically) little reason to do this. If you need to use a specific allocator, you can define a custom operator new overload.

VoidStar
  • 5,241
  • 1
  • 31
  • 45
  • I would combine the second and third lines into `A* obj = new(a) A();`, which would avoid the need for a `reinterpret_cast` to an invalid type (the pointer returned from `malloc` does not point to an `A` until the `A` is constructed). – Mankarse Mar 29 '15 at 10:27
  • In your code you have use new. The question is, how to do sush things instead using new(obj) A() ? –  Mar 29 '15 at 10:28
  • @Վարդան Գրիգորյան : You are misunderstanding: new in this context is called placement new and it does not allocate memory. It invokes the constructor of A() only. – VoidStar Mar 29 '15 at 10:30
  • 1
    @ՎարդանԳրիգորյան: It isn't possible to call a constructor directly without using `new`. (Or to put it differently, placement new *is* the `C++` mechanism for calling a constructor directly). – Mankarse Mar 29 '15 at 10:30
  • Ok, is it possible to call the constructor explicitly, using a pointer which returned by malloc ? –  Mar 29 '15 at 10:31
  • @Վարդան Գրիգորյան : Yes, placement new is the syntax for explicitly invoking the constructor. – VoidStar Mar 29 '15 at 10:32
  • 3
    Shouldn't the second line read `A* obj = new(a) A();` in the simplified version? – Avi Ginsburg Mar 29 '15 at 10:35
  • @Avi Ginsburg: Yes, careless pasting mistake, fixed ;) – VoidStar Mar 29 '15 at 11:01
1

Beware, malloc returns an address that is aligned to 8 bytes. If your class just have a

char a[6];

member you are wasting 2 bytes (well if you have only 1 char or 1 bool you'll be wastin 7 bytes), while if you have a

v4si a;

vector of 4 bytes for SIMD instructions, you could have a wrong alignment wich require extra instructions to re-align it correctly.

Not wasting memory:

class TinyClass{
    char c[3];
public:
    TinyClass( char c1, char c2, char c3){
        c[0] = c1; c[1] = c2; c[2] = c3;
    }
};

Basically you have to create more than one object at a time (but they also must be destroyed at same time, so probably that's not suitable for you)

#include <new> //not needed if you already include any STL header

int number_of_items = 6;
void* a = malloc(sizeof(TinyClass)*number_of_items);
TinyClass * Ptr = reinterpret_cast< TinyClass* > (a);
for(int i=0; i<number_of_items; i++)
    new(&Ptr[i]) TinyClass('a','b','c');

//later
for(int i=0; i<number_of_items; i++)
    Ptr[i].~TinyClass();  //destructor
Ptr = NULL; // or Ptr = nullptr; if you have c++11
free(a);

.

Forcing alignement bigger than 8 bytes:

C++ possible implementation of aligned malloc

Of course forget what I said if you don't mind performance or memory waste ^^, because that's a bit bloat code.

Is that the same in C++? Not exactly, using "new" in c++ returns a pointer wich is at least aligned to what is needed, but there's no guarantee the implementation will not have a bigger alignement)

Community
  • 1
  • 1
CoffeDeveloper
  • 7,961
  • 3
  • 35
  • 69