2

Is it possible to pass some parameters to constructor of a class inside a constructor of another class using malloc? I can do that with new. I need to do the same thing with malloc: (If it does not make sense, consider that I am using a custom allocator instead of malloc)

Class A_Class ... {
       public:
       B_Class *b;
...
     A_Class: ...
      { b = new B_Class (c1, c2, c3);
      } // end of constructor
}

Now with malloc:

Class A_Class ... {
       public:
       B_Class *b;
...
     A_Class: ...
      { b = (B_Class*) malloc (sizeof(*b)); 
        ??????????????? }
}
Donato Szilagyi
  • 4,279
  • 4
  • 36
  • 53
Computer_guy
  • 807
  • 2
  • 11
  • 19

4 Answers4

13

malloc allocates raw memory. There's no point in trying to pass constructor arguments to it because it doesn't call any constructors.

If you have to work with raw memory, it is up to you to construct an object in previously allocated raw memory by using "placement new" syntax

...
void *raw_b = malloc(sizeof *b);
b = new(raw_b) B_Class(c1, c2, c3); // <- placement new 
...

Numerically, the value of b will be the same as raw_b, i.e. it is possible to get by without an extra raw_b pointer. But I prefer to do it this way, with an intermediate void * pointer, to avoid ugly casts.

Be careful when destroying such objects, of course. Custom allocation requires custom deletion. You can't just delete your b in general case. A symmetrical custom deletion sequence would involve an explicit destructor call followed by raw memory deallocation

b->~B_Class(); // <- explicit destructor call
free(b);

P.S. You might consider going a different route: overloading operator new/operator delete in your class instead of spelling out custom allocation explicitly every time you need to create an object.

PLNech
  • 3,087
  • 1
  • 23
  • 52
AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • Thanks Andrey. Doesn't it allocate a new memory for raw_b? Are you sure that this way raw_b uses the memory that is allocated at the first line?? – Computer_guy Jul 03 '12 at 15:03
  • @Amir Reza: Yes, that the whole point of that standard feature. This specific form of placement new does exactly that: constructs an object at the given location in pre-allocated memory. – AnT stands with Russia Jul 03 '12 at 15:06
  • 1
    Aside from avoiding casts, the other advantage of the `void*` pointer is that if you get your `B_Class*` from the result of `new`, then you can't get carried away thinking that your pointer-to-B_Class points to an actual `B_Class` object before it really does. – Steve Jessop Jul 03 '12 at 15:06
  • Thanks everyone for the answers. As another question, is it possible to predict the allocated memory for the members of class B? suppose, instead of "malloc(sizeof *b)", we say "malloc(N*sizeof *b)". Does it give us any control over the member of the class? Would they be allocated from this large pre-allocated memory (N is a big number)? If not, what is your suggestion? Thanks – Computer_guy Jul 03 '12 at 15:55
  • @Computer_guy: Members of the class are initialized by the constructor. It is you who writes the initialization code inside the constructor, so it is entirely up to you to initialize them in any way you want. You want some sort of custom initialization - implement it. You want everything to reside in one memory block - allocate it and pass it around so that everything that needs memory gets it from that block. It is, again, something you implement manually. It won't happen by itself. – AnT stands with Russia Jul 03 '12 at 19:32
2

No, it's not possible. If it is designed for C++, then your custom allocator will have a function called construct that is used for this (and rebind to get an allocator that can construct a different type).

In C++03, this only does copy-construction, so you would have to call allocator.construct(ptr, B_Class(c1, c2, c3)) and the class has to be copyable. In C++11, allocators can construct from any arguments.

If your allocator is designed for C, then you'll have to use so-called "placement new". Of course, malloc is designed for C. You should look it up for yourself, but the syntax is:

b = (B_Class*) malloc(sizeof(*b));
new ((void*)b) B_Class(c1,c2,c3);

Remember to handle any exception that the constructor may throw, and free the buffer.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
0

malloc doesn't call constructors. There's no way to pass parameters to a function which doesn't get called. As for the custom allocator, you'll have to be more specific as to what you're doing. Who's allocating what where using the custom allocator. Usually, custom allocators are only used for allocation; they aren't concerned with the constructor either.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • Thanks James. Of course it doesn't call the constructors. But why can't I pass the parameters after allocating the memory? something like what "new" does itself. – Computer_guy Jul 03 '12 at 15:00
  • Because you're not calling any constructor, even after allocating the memory. The only way you can pass parameters to a constructor is with the new operator. (Possibly placement new, if you've separated allocation from initialization. Or with a custom operator new.) – James Kanze Jul 03 '12 at 15:20
0

You can create static method for constructing B:

class B_Class
{
     public static B_Class* MallocMe(SomeParam param)
     {
           B_Class* retval = (B_Class*) malloc(sizeof(B_Class));
           retval->Construct(param);
           return retval;
     }
 ....
Agent_L
  • 4,960
  • 28
  • 30