Thread overview | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
March 21, 2017 Delay allocating class instance in stack. | ||||
---|---|---|---|---|
| ||||
Hello! I read documentation about memory management and can't find description about delay allocation of instance. I have a method marked by @nogc. This method takes boolean variable. If this variable is true I want to construct object with one set of parameters else I want to construct object with another set of parameters. Take a look at code for clearance. void method(bool flag) @nogc { scope MyClass obj; if(flag) { obj = new MyClass(1); } else { obj = new MyClass(2); } // using obj } But this code CAN'T be compiled. How should I declare object for delay construction. Thanks. |
March 21, 2017 Re: Delay allocating class instance in stack. | ||||
---|---|---|---|---|
| ||||
Posted in reply to ANtlord | You probably want[0] to allocate a class on the stack instead of doing this. [0] http://dlang.org/phobos/std_typecons.html#.scoped |
March 21, 2017 Re: Delay allocating class instance in stack. | ||||
---|---|---|---|---|
| ||||
Posted in reply to rikki cattermole | On Tuesday, 21 March 2017 at 08:12:36 UTC, rikki cattermole wrote:
> You probably want[0] to allocate a class on the stack instead of doing this.
>
> [0] http://dlang.org/phobos/std_typecons.html#.scoped
If I will use it I won't use @nogc. Is the only one case?
|
March 21, 2017 Re: Delay allocating class instance in stack. | ||||
---|---|---|---|---|
| ||||
Posted in reply to ANtlord | On 03/21/2017 01:08 AM, ANtlord wrote: > void method(bool flag) @nogc > { > scope MyClass obj; > if(flag) { > obj = new MyClass(1); > } else { > obj = new MyClass(2); > } > // using obj > } Another option is std.conv.emplace: import std.conv : emplace; class MyClass { this(int) @nogc { } ~this() @nogc { } } void method(bool flag) @nogc { void[__traits(classInstanceSize, MyClass)] buffer = void; MyClass obj; if(flag) { obj = emplace!MyClass(buffer, 1); } else { obj = emplace!MyClass(buffer, 2); } // Unfortunately, destroy() is not @nogc // scope(exit) destroy(obj); } void main() { method(false); method(true); } Ali |
March 21, 2017 Re: Delay allocating class instance in stack. | ||||
---|---|---|---|---|
| ||||
Posted in reply to ANtlord | On Tuesday, 21 March 2017 at 08:08:24 UTC, ANtlord wrote:
> Hello! I read documentation about memory management and can't find description about delay allocation of instance. I have a method marked by @nogc. This method takes boolean variable. If this variable is true I want to construct object with one set of parameters else I want to construct object with another set of parameters. Take a look at code for clearance.
>
> void method(bool flag) @nogc
> {
> scope MyClass obj;
> if(flag) {
> obj = new MyClass(1);
> } else {
> obj = new MyClass(2);
> }
> // using obj
> }
>
> But this code CAN'T be compiled. How should I declare object for delay construction.
> Thanks.
Try scope obj = new MyClass(flag ? 1 : 2);
In essence you should never need to delay construction.
Just construct the object as soon as you have everything to construct it.
which includes conditions.
|
March 22, 2017 Re: Delay allocating class instance in stack. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Tuesday, 21 March 2017 at 08:46:43 UTC, Ali Çehreli wrote:
> Another option is std.conv.emplace:
>
> import std.conv : emplace;
>
> class MyClass {
> this(int) @nogc {
> }
>
> ~this() @nogc {
> }
> }
>
> void method(bool flag) @nogc
> {
> void[__traits(classInstanceSize, MyClass)] buffer = void;
> MyClass obj;
>
> if(flag) {
> obj = emplace!MyClass(buffer, 1);
> } else {
> obj = emplace!MyClass(buffer, 2);
> }
>
> // Unfortunately, destroy() is not @nogc
> // scope(exit) destroy(obj);
Thank you for clarification. But I have one more question. Do I have to use destroy for deallocating object from stack?
|
March 22, 2017 Re: Delay allocating class instance in stack. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stefan Koch | On Tuesday, 21 March 2017 at 12:30:57 UTC, Stefan Koch wrote:
>
> Try scope obj = new MyClass(flag ? 1 : 2);
>
> In essence you should never need to delay construction.
> Just construct the object as soon as you have everything to construct it.
> which includes conditions.
Yes I know it. I prepare all input variables before construction of object usually. I just want to know possibilty of the case described above.
|
March 21, 2017 Re: Delay allocating class instance in stack. | ||||
---|---|---|---|---|
| ||||
Posted in reply to ANtlord | On 03/21/2017 09:57 PM, ANtlord wrote: > On Tuesday, 21 March 2017 at 08:46:43 UTC, Ali Çehreli wrote: >> Another option is std.conv.emplace: >> >> import std.conv : emplace; >> >> class MyClass { >> this(int) @nogc { >> } >> >> ~this() @nogc { >> } >> } >> >> void method(bool flag) @nogc >> { >> void[__traits(classInstanceSize, MyClass)] buffer = void; >> MyClass obj; >> >> if(flag) { >> obj = emplace!MyClass(buffer, 1); >> } else { >> obj = emplace!MyClass(buffer, 2); >> } >> >> // Unfortunately, destroy() is not @nogc >> // scope(exit) destroy(obj); > > Thank you for clarification. But I have one more question. Do I have to > use destroy for deallocating object from stack? Yes because what is going out of scope are two things: - A buffer - A MyClass reference Neither of those have destructors. (emplace is just a library function that does something with that buffer but the compiler cannot know that there is an object that we want destructed.) Here is a hack that defines a destroyNoGC() that allows one to call the destructor is a @nogc context: import std.stdio; import std.conv : emplace; class MyClass { this(int) @nogc { } ~this() @nogc { printf("~this\n"); } } // Adapted from std.traits.SetFunctionAttributes documentation import std.traits; auto assumeNoGC(T)(T t) if (isFunctionPointer!T || isDelegate!T) { enum attrs = functionAttributes!T | FunctionAttribute.nogc; return cast(SetFunctionAttributes!(T, functionLinkage!T, attrs)) t; } @nogc void function(Object) destroyNoGC; static this() { destroyNoGC = assumeNoGC((Object obj) { destroy(obj); }); } void method(bool flag) @nogc { void[__traits(classInstanceSize, MyClass)] buffer = void; MyClass obj; if(flag) { obj = emplace!MyClass(buffer, 1); } else { obj = emplace!MyClass(buffer, 2); } scope(exit) { destroyNoGC(obj); } } void main() { method(false); method(true); } Gotta love D for allowing such code but it comes with surprises. Why do we suddenly get two destructor calls? ~this ~this Ali |
March 21, 2017 Re: Delay allocating class instance in stack. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On 03/21/2017 11:47 PM, Ali Çehreli wrote: > method(false); > method(true); > } > > Gotta love D for allowing such code but it comes with surprises. Why do > we suddenly get two destructor calls? > > ~this > ~this Answering own question: There are two destructor calls because I call method() twice. Ali |
March 22, 2017 Re: Delay allocating class instance in stack. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Wednesday, 22 March 2017 at 06:47:26 UTC, Ali Çehreli wrote:
> On 03/21/2017 09:57 PM, ANtlord wrote:
> > Thank you for clarification. But I have one more question. Do
> I have to
> > use destroy for deallocating object from stack?
>
> Yes because what is going out of scope are two things:
>
> - A buffer
> - A MyClass reference
>
Oh I got it. I have to use `destroy` in this case. If I use `scope` I haven't buffer and MyClass reference then I can don't use `destroy`. Do I understand correctly?
|
Copyright © 1999-2021 by the D Language Foundation