www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Doubt about Struct and members

reply matheus <matheus gmail.com> writes:
Hi,

I was doing some tests and this code:

import std;

struct S{
     string[] s = ["ABC"];
     int i = 123;
}

void foo(bool b, string str){
     S t1;

     writeln("t1.s: ", t1.s, ", t1.s.ptr: ", t1.s.ptr, " t1.i: ", 
t1.i);

     if(b){
     	t1.s[0] = str;
     }else{
     	t1.s = [str];
     }

     t1.i = 456;
     S t2;

     writeln("t1.s: ", t1.s, ", t1.s.ptr: ", t1.s.ptr, " t1.i: ", 
t1.i);

     writeln("t2.s: ", t2.s, ", t2.s.ptr: ", t2.s.ptr, " t2.i: ", 
t2.i);
     writeln("");
}

void main(){
     foo(false, "DEF");
     foo(true, "DEF");
     foo(false, "XYZ");
}

Outputs:

t1.s: ["ABC"], t1.s.ptr: 56421C6D7010 t1.i: 123
t1.s: ["DEF"], t1.s.ptr: 7EFC725E6000 t1.i: 456
t2.s: ["ABC"], t2.s.ptr: 56421C6D7010 t2.i: 123

t1.s: ["ABC"], t1.s.ptr: 56421C6D7010 t1.i: 123
t1.s: ["DEF"], t1.s.ptr: 56421C6D7010 t1.i: 456
t2.s: ["DEF"], t2.s.ptr: 56421C6D7010 t2.i: 123

t1.s: ["DEF"], t1.s.ptr: 56421C6D7010 t1.i: 123
t1.s: ["XYZ"], t1.s.ptr: 7EFC725E6020 t1.i: 456
t2.s: ["DEF"], t2.s.ptr: 56421C6D7010 t2.i: 123

As you can see:

     t1.s = [str];

Just changed generated a new address only for t1.s, on the other 
hand:

     t1.s[0] = str;

Changed the value pointed by S.s entirely (The other "instance" 
t2 since points to the same address now has the new value too).

Is this intended?

Matheus.
Jan 08
parent reply "H. S. Teoh" <hsteoh qfbox.info> writes:
On Mon, Jan 08, 2024 at 05:28:50PM +0000, matheus via Digitalmars-d-learn wrote:
 Hi,
 
 I was doing some tests and this code:
 
 import std;
 
 struct S{
     string[] s = ["ABC"];
     int i = 123;
 }
[...] It's not recommended to use initializers to initialize mutable array-valued members, because it probably does not do what you think it does. What the above code does is to store the array ["ABC"] somewhere in the program's pre-initialized data segment and set s to point to that by default. It does NOT allocated a new array literal every time you create a new instance of S; every instance of S will *share* the same array value unless you reassign it. As such, altering the contents array may cause the new contents to show up in other instances of S. This behaviour is generally harmless if your array is immutable. In fact, it saves space in your executable by reusing the same data for multiple instances of s. It also avoids repeated GC allocations at runtime. However, if you're banking on each instance of S getting its own copy of the array, you're in for a surprise. In this case, what you want is to use a ctor to initialize it rather than the above initializer. T -- Right now I'm having amnesia and deja vu at the same time. I think I've forgotten this before.
Jan 08
parent matheus <matheus gmail.com> writes:
On Monday, 8 January 2024 at 17:56:19 UTC, H. S. Teoh wrote:
 ...
 It's not recommended to use initializers to initialize mutable 
 array-valued members, because it probably does not do what you 
 think it does.  What the above code does is to store the array 
 ["ABC"] somewhere in the program's pre-initialized data segment 
 and set s to point to that by default. It does NOT allocated a 
 new array literal every time you create a new instance of S; 
 every instance of S will *share* the same array value unless 
 you reassign it.  As such, altering the contents array may 
 cause the new contents to show up in other instances of S.

 This behaviour is generally harmless if your array is 
 immutable. In fact, it saves space in your executable by 
 reusing the same data for multiple instances of s. It also 
 avoids repeated GC allocations at runtime.
 ...
First of all thanks for replying, Yes I understood the behavior since I even looked the code generated: https://godbolt.org/z/xnsbern9f =] Maybe my question was poorly written (I'm ESL), but you answered in the other Topic:
 "(Whether the current behaviour should be changed is up for 
 debate, though. This definitely isn't the first time users have 
 run into this. In fact just today somebody else asked the same 
 question on D.learn. So it's definitely in the territory of 
 "does not do the expected thing", which is an indication that 
 the default behaviour was poorly chosen.)"
I was in doubt about if this was intended or not... and it seems the case. I'm not saying it is wrong by any means, I just found a bit tricky based on the two ways it could change the value pointed by the address and/or the address of the member itself. Again thanks, Matheus.
Jan 08