digitalmars.D - struct constructors and destructors.
- Danni Coy via Digitalmars-d (14/14) Jul 19 2017 Is there a reason that the following code
- Stefan Koch (9/23) Jul 19 2017 What happens is this.
- Danni Coy via Digitalmars-d (2/11) Jul 19 2017
- Stefan Koch (5/20) Jul 19 2017 I posted pseudo code to show you that you are creating a
- Adam D. Ruppe (7/9) Jul 19 2017 No, that's not the case. There is a temporary, but its destructor
- Danni Coy via Digitalmars-d (5/27) Jul 19 2017 Yeah somehow I read that as a question -- must be getting tired.
- SrMordred (5/33) Jul 19 2017 Hm, isnt that wrong?
- SrMordred (4/39) Jul 19 2017 No Sorry, it behaves almost the same.
- Danni Coy via Digitalmars-d (3/48) Jul 20 2017 Is there a way to delay the initialisation of a struct?
- Petar Kirov [ZombineDev] (29/82) Jul 20 2017 void initialization + emplace:
- Adam D. Ruppe (6/7) Jul 20 2017 Did my post even go through?
- Adam D. Ruppe (26/27) Jul 19 2017 Are you sure that's what's actually happening?
Is there a reason that the following code struct Foo { this (string name) { do_something(name); } ~this() { undo_something(); } } Foo foo = void; void open() { foo = Foo("test"); // <- this line } tries to OpAssign foo to itself then calls foo's destructor?
Jul 19 2017
On Wednesday, 19 July 2017 at 07:48:28 UTC, Danni Coy wrote:Is there a reason that the following code struct Foo { this (string name) { do_something(name); } ~this() { undo_something(); } } Foo foo = void; void open() { foo = Foo("test"); // <- this line } tries to OpAssign foo to itself then calls foo's destructor?What happens is this. void open() { foo = () { Foo _tmp = Foo.__ctor("test"); return _tmp; } (); }
Jul 19 2017
On Wed, Jul 19, 2017 at 7:09 PM, Stefan Koch via Digitalmars-d < digitalmars-d puremagic.com> wrote:What happens is this. void open() { foo = () { Foo _tmp = Foo.__ctor("test"); return _tmp; } (); } Error: need 'this' for 'this' of type 'ref Foo(string s)'
Jul 19 2017
On Wednesday, 19 July 2017 at 12:23:06 UTC, Danni Coy wrote:On Wed, Jul 19, 2017 at 7:09 PM, Stefan Koch via Digitalmars-d < digitalmars-d puremagic.com> wrote:I posted pseudo code to show you that you are creating a temporary. Which leaves the scope after assigning. And therefore triggers the destructor.What happens is this. void open() { foo = () { Foo _tmp = Foo.__ctor("test"); return _tmp; } (); } Error: need 'this' for 'this' of type 'ref Foo(string s)'
Jul 19 2017
On Wednesday, 19 July 2017 at 12:34:50 UTC, Stefan Koch wrote:Which leaves the scope after assigning. And therefore triggers the destructor.No, that's not the case. There is a temporary, but its destructor is not called. The existing object in `foo` is destroyed, so the new one can be moved (and indeed moved, not copied, so no postblit, no dtor call, though it might or might not invalidate internal pointers - that's why the spec bans those) into its place.
Jul 19 2017
Yeah somehow I read that as a question -- must be getting tired. That makes more sense. is there any way to On Wed, Jul 19, 2017 at 10:34 PM, Stefan Koch via Digitalmars-d < digitalmars-d puremagic.com> wrote:On Wednesday, 19 July 2017 at 12:23:06 UTC, Danni Coy wrote:On Wed, Jul 19, 2017 at 7:09 PM, Stefan Koch via Digitalmars-d < digitalmars-d puremagic.com> wrote:I posted pseudo code to show you that you are creating a temporary. Which leaves the scope after assigning. And therefore triggers the destructor.What happens is this. void open() { foo = () { Foo _tmp = Foo.__ctor("test"); return _tmp; } (); } Error: need 'this' for 'this' of type 'ref Foo(string s)'
Jul 19 2017
On Wednesday, 19 July 2017 at 09:09:40 UTC, Stefan Koch wrote:On Wednesday, 19 July 2017 at 07:48:28 UTC, Danni Coy wrote:Hm, isnt that wrong? If I destroy resources on the dtor, wouldn't it invalidate the resource on the copy? Also, C++ behaves differentlyIs there a reason that the following code struct Foo { this (string name) { do_something(name); } ~this() { undo_something(); } } Foo foo = void; void open() { foo = Foo("test"); // <- this line } tries to OpAssign foo to itself then calls foo's destructor?What happens is this. void open() { foo = () { Foo _tmp = Foo.__ctor("test"); return _tmp; } (); }
Jul 19 2017
On Wednesday, 19 July 2017 at 14:09:32 UTC, SrMordred wrote:On Wednesday, 19 July 2017 at 09:09:40 UTC, Stefan Koch wrote:No Sorry, it behaves almost the same. just in D ctor and dtor are not called on declaration even if you drop " = void".On Wednesday, 19 July 2017 at 07:48:28 UTC, Danni Coy wrote:Hm, isnt that wrong? If I destroy resources on the dtor, wouldn't it invalidate the resource on the copy? Also, C++ behaves differentlyIs there a reason that the following code struct Foo { this (string name) { do_something(name); } ~this() { undo_something(); } } Foo foo = void; void open() { foo = Foo("test"); // <- this line } tries to OpAssign foo to itself then calls foo's destructor?What happens is this. void open() { foo = () { Foo _tmp = Foo.__ctor("test"); return _tmp; } (); }
Jul 19 2017
On Thu, Jul 20, 2017 at 12:19 AM, SrMordred via Digitalmars-d < digitalmars-d puremagic.com> wrote:On Wednesday, 19 July 2017 at 14:09:32 UTC, SrMordred wrote:Is there a way to delay the initialisation of a struct?On Wednesday, 19 July 2017 at 09:09:40 UTC, Stefan Koch wrote:No Sorry, it behaves almost the same. just in D ctor and dtor are not called on declaration even if you drop " = void".On Wednesday, 19 July 2017 at 07:48:28 UTC, Danni Coy wrote:Hm, isnt that wrong? If I destroy resources on the dtor, wouldn't it invalidate the resource on the copy? Also, C++ behaves differentlyIs there a reason that the following code struct Foo { this (string name) { do_something(name); } ~this() { undo_something(); } } Foo foo = void; void open() { foo = Foo("test"); // <- this line } tries to OpAssign foo to itself then calls foo's destructor?What happens is this. void open() { foo = () { Foo _tmp = Foo.__ctor("test"); return _tmp; } (); }
Jul 20 2017
On Thursday, 20 July 2017 at 09:09:42 UTC, Danni Coy wrote:On Thu, Jul 20, 2017 at 12:19 AM, SrMordred via Digitalmars-d < digitalmars-d puremagic.com> wrote:void initialization + emplace: struct Foo { this (string name) { create_count++; } ~this() { destroy_count--; } } int create_count; int destroy_count; Foo foo = void; void main() { import std.stdio; import std.conv : emplace; writefln("this(string) ran %s times.", create_count); writefln("~this() ran %s times.", destroy_count); emplace(&foo, "test"); writeln("--- emplace ---"); writefln("this(string) ran %s times.", create_count); writefln("~this() ran %s times.", destroy_count); } this(string) ran 0 times. ~this() ran 0 times. --- emplace --- this(string) ran 1 times. ~this() ran 0 times. https://is.gd/G06GvKOn Wednesday, 19 July 2017 at 14:09:32 UTC, SrMordred wrote:Is there a way to delay the initialisation of a struct?On Wednesday, 19 July 2017 at 09:09:40 UTC, Stefan Koch wrote:No Sorry, it behaves almost the same. just in D ctor and dtor are not called on declaration even if you drop " = void".On Wednesday, 19 July 2017 at 07:48:28 UTC, Danni Coy wrote:Hm, isnt that wrong? If I destroy resources on the dtor, wouldn't it invalidate the resource on the copy? Also, C++ behaves differentlyIs there a reason that the following code struct Foo { this (string name) { do_something(name); } ~this() { undo_something(); } } Foo foo = void; void open() { foo = Foo("test"); // <- this line } tries to OpAssign foo to itself then calls foo's destructor?What happens is this. void open() { foo = () { Foo _tmp = Foo.__ctor("test"); return _tmp; } (); }
Jul 20 2017
On Wednesday, 19 July 2017 at 14:09:32 UTC, SrMordred wrote:Hm, isnt that wrong?Did my post even go through? http://forum.dlang.org/post/udaxeyujrafklzpwwftf forum.dlang.org What's going on here is actually pretty simple. Though calling a destructor on a default-initialized struct should always be valid anyway.
Jul 20 2017
On Wednesday, 19 July 2017 at 07:48:28 UTC, Danni Coy wrote:tries to OpAssign foo to itself then calls foo's destructor?Are you sure that's what's actually happening? What should be happening there is: 1) it calls Foo's constructor on a temporary location 2) it destroys the old contents of `foo` 3) it moves the Foo from (1) into the variable freshly destroyed from (2) It is void initialized, so you might think there are no old contents of foo, but the compiler doesn't know this for certain (consider you called `open` twice. would be true the first time, but not the second time. the compiler needs to generate the function so it works both times). There is a function which the compiler knows will only be called once though: a static constructor. --- shared static this() { foo = Foo("test"); } --- That only runs once, and the compiler will skip the destruction of old `foo`.... as long as it isn't already initialized. Ironically, removing the `= void` from it causes the compiler to realize this and only use the ctor initialization. Otherwise, it tries to destroy the existing item, apparently not realizing it was void.... arguably a small compiler bug there.
Jul 19 2017