www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - struct constructors and destructors.

reply Danni Coy via Digitalmars-d <digitalmars-d puremagic.com> writes:
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
next sibling parent reply Stefan Koch <uplink.coder googlemail.com> writes:
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
next sibling parent reply Danni Coy via Digitalmars-d <digitalmars-d puremagic.com> writes:
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
parent reply Stefan Koch <uplink.coder googlemail.com> writes:
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:

 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)'
I posted pseudo code to show you that you are creating a temporary. Which leaves the scope after assigning. And therefore triggers the destructor.
Jul 19 2017
next sibling parent Adam D. Ruppe <destructionator gmail.com> writes:
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
prev sibling parent Danni Coy via Digitalmars-d <digitalmars-d puremagic.com> writes:
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:


 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)'
I posted pseudo code to show you that you are creating a temporary. Which leaves the scope after assigning. And therefore triggers the destructor.
Jul 19 2017
prev sibling parent reply SrMordred <patric.dexheimer gmail.com> writes:
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:
 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; } (); }
Hm, isnt that wrong? If I destroy resources on the dtor, wouldn't it invalidate the resource on the copy? Also, C++ behaves differently
Jul 19 2017
next sibling parent reply SrMordred <patric.dexheimer gmail.com> writes:
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:
 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; } (); }
Hm, isnt that wrong? If I destroy resources on the dtor, wouldn't it invalidate the resource on the copy? Also, C++ behaves differently
No Sorry, it behaves almost the same. just in D ctor and dtor are not called on declaration even if you drop " = void".
Jul 19 2017
parent reply Danni Coy via Digitalmars-d <digitalmars-d puremagic.com> writes:
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:

 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:

 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; } (); }
Hm, isnt that wrong? If I destroy resources on the dtor, wouldn't it invalidate the resource on the copy? Also, C++ behaves differently
No Sorry, it behaves almost the same. just in D ctor and dtor are not called on declaration even if you drop " = void".
Is there a way to delay the initialisation of a struct?
Jul 20 2017
parent Petar Kirov [ZombineDev] <petar.p.kirov gmail.com> writes:
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:

 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:

 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; } (); }
Hm, isnt that wrong? If I destroy resources on the dtor, wouldn't it invalidate the resource on the copy? Also, C++ behaves differently
No Sorry, it behaves almost the same. just in D ctor and dtor are not called on declaration even if you drop " = void".
Is there a way to delay the initialisation of a struct?
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/G06GvK
Jul 20 2017
prev sibling parent Adam D. Ruppe <destructionator gmail.com> writes:
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
prev sibling parent Adam D. Ruppe <destructionator gmail.com> writes:
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