Thread overview
Separate allocation and construction?
Jun 05, 2014
Chris Williams
Jun 05, 2014
Adam D. Ruppe
Jun 05, 2014
Chris Williams
Jun 05, 2014
Ali Çehreli
June 05, 2014
If I wanted to allocate memory for a class and then call its constructor as two separate steps, while still having the object be managed by the garbage collector, is there any way to do that?

I believe that I've figured out a way to accomplish the first step, but not the second.

import std.stdio;

class Foo {
    this(string bar) {
        writeln(bar);
    }
}

void main() {
    Foo f = (new Foo[1])[0];
    f("Hello"); // doesn't compile
}
June 05, 2014
On Thursday, 5 June 2014 at 22:22:16 UTC, Chris Williams wrote:
> If I wanted to allocate memory for a class and then call its constructor as two separate steps, while still having the object be managed by the garbage collector, is there any way to do that?


Check out std.conv.emplace
http://dlang.org/phobos/std_conv.html#emplace

First, allocate the memory block for the class. The size is __traits(classInstanceSize, Yourclass). Then slice it:

enum size = __traits(classInstanceSize, YourClass);
auto memory = GC.malloc(size)[0 .. size];


Then use emplace to do the construction:

auto obj = emplace!YourClass(memory, ctor_args...);


GC.malloc can be found in import core.memory; http://dlang.org/phobos/core_memory.html#malloc


Note that you can also use other memory allocators here if you didn't want it gc'd.
June 05, 2014
On Thursday, 5 June 2014 at 22:25:03 UTC, Adam D. Ruppe wrote:
> On Thursday, 5 June 2014 at 22:22:16 UTC, Chris Williams wrote:
>> If I wanted to allocate memory for a class and then call its constructor as two separate steps, while still having the object be managed by the garbage collector, is there any way to do that?
>
>
> Check out std.conv.emplace
> http://dlang.org/phobos/std_conv.html#emplace
>
> First, allocate the memory block for the class. The size is __traits(classInstanceSize, Yourclass). Then slice it:
>
> enum size = __traits(classInstanceSize, YourClass);
> auto memory = GC.malloc(size)[0 .. size];

Why slice? There seems to be a version of emplace that accepts a pointer, which is what GC.malloc() seems to return.
June 05, 2014
On 06/05/2014 03:47 PM, Chris Williams wrote:
> On Thursday, 5 June 2014 at 22:25:03 UTC, Adam D. Ruppe wrote:
>> On Thursday, 5 June 2014 at 22:22:16 UTC, Chris Williams wrote:
>>> If I wanted to allocate memory for a class and then call its
>>> constructor as two separate steps, while still having the object be
>>> managed by the garbage collector, is there any way to do that?
>>
>>
>> Check out std.conv.emplace
>> http://dlang.org/phobos/std_conv.html#emplace
>>
>> First, allocate the memory block for the class. The size is
>> __traits(classInstanceSize, Yourclass). Then slice it:
>>
>> enum size = __traits(classInstanceSize, YourClass);
>> auto memory = GC.malloc(size)[0 .. size];
>
> Why slice? There seems to be a version of emplace that accepts a
> pointer, which is what GC.malloc() seems to return.

That overload returns a T* but we need a class variable. I think we should accept it that it is reserved for non-class types (as the documentation also indicates).

Ali