Potential strategy for avoiding problems with copy of a struct (maybe??)

jfondren julian.fondren at gmail.com
Sun Aug 22 11:10:33 UTC 2021


On Sunday, 22 August 2021 at 07:58:12 UTC, james.p.leblanc wrote:
> Hello,
>
> Question about a possible strategy to avoid problems with
> undesired/unintended copying of a structure:
>
> 1) We have a struct, call this **Foo**.
>
> 2) We instantiate it with,   **x = Foo(a,b,c);**
>        a.  our constructor will initialize a field:  
> **this.myadd = &this**
>        b.  this capture the address of our original "x" in 
> x.myadd.

Sorry, I don't follow this at all.

Consider:

```d
struct Foo {
     int a, b, c;
     Foo* myadd;

     this(int a, int b, int c) {
         myadd = &this;
         this.a = a;
         this.b = b;
         this.c = c;
     }
}

void main() {
     import std.stdio : writeln;

     Foo x; // initialized with (0, 0, 0, null)
     writeln(&x); // a memory location
     x = Foo(1, 2, 3); // (1, 2, 3, &x)

     writeln(&x); // the exact same memory location
     writeln(x.myadd.a); // 1, rather than 0, because &x==x.myadd
}
```

There's no saving the original "x" here, it's overwritten by the 
assignment. Are you sure you don't want classes instead, to get 
reference semantics?

> 4) Our goal is to avoid problems with any accidental copying
>    of x ... say by doing:  **auto y=x;**
>
> 5) the copy of step 4 **does not use the constructor**, thus 
> y.myadd
>    would contain the address of x (and not y)

`auto y=x;` actually does call object lifetime functions.

```d
struct CountCopies {
     int copies;

     this(this) { // postblit
         copies++;
     }
}

unittest {
     CountCopies x;
     auto y = x;
     auto z = y;
     assert(x.copies == 0);
     assert(y.copies == 1);
     assert(z.copies == 2);
}
```

or with a copy constructor,

```d
struct CountCopies {
     int copies;

     this(ref return scope const CountCopies rhs) { // copy 
constructor
         copies = rhs.copies + 1;
     }
     @disable this(this); // helps pre-copy-constructor compilers 
reject this code
}

unittest {
     CountCopies x;
     auto y = x;
     auto z = y;
     assert(x.copies == 0);
     assert(y.copies == 1);
     assert(z.copies == 2);
}
```

> Some initial experiments lead me to believe this may acheive
> part of what I would like.  But, it feels very "hackish" and
> ugly.
>
> Is there a better way?

If you don't get an answer that you like, I suggesting posting 
functional code and then stating your dissastisfactions with it.


More information about the Digitalmars-d-learn mailing list