digitalmars.D.learn - confusion about structs
- =?ISO-8859-1?Q?Christian_K=F6stlin?= (48/48) Sep 25 2011 I have this small program, which does some data handling with structs:
- Andrej Mitrovic (10/10) Sep 25 2011 This should make things clearer for you:
- =?ISO-8859-1?Q?Christian_K=F6stlin?= (4/14) Sep 26 2011 Thanks for the explanation!
- Jonathan M Davis (27/81) Sep 25 2011 as
- Jonathan M Davis (9/22) Sep 25 2011 Ah. Yes. Okay. There isn't a bug here then (at least not in the compiler...
I have this small program, which does some data handling with structs: struct App { private int[] fData; this(size_t initialSize) { fData = new int[initialSize]; } void put(int i) { fData[0] = i; } int[] get() { return fData; } } struct Builder { int i; App app = App(2); this(int i_) { i = i_; // app = App(2); } void put(int v) { app.put(v); } int[] get() { return app.get(); } } int[] get(int i) { auto b = Builder(i); b.put(i); return b.get(); } unittest { auto h1 = get(1); auto h2 = get(2); assert(h1[0] == 1); assert(h2[0] == 2); } int main(string[] args) { return 0; } compiling this with dmd -unittest shows, that the tests are failing. if you comment in the line // app = App(2); then the tests work as expected. Could you please explain what struct Builder { App app = App(2); } does exactly compared to doing thins in the structs constructor? thanks in advance christian
Sep 25 2011
This should make things clearer for you: unittest { auto h1 = get(1); auto h2 = get(2); assert(h1 is h2); // both reference the same array } Field initialization is only done once (once per thread, or if a field is shared once on app start) and not each time you call the constructor.
Sep 25 2011
On 09/26/2011 12:04 AM, Andrej Mitrovic wrote:This should make things clearer for you: fittest { auto h1 = get(1); auto h2 = get(2); assert(h1 is h2); // both reference the same array } Field initialization is only done once (once per thread, or if a field is shared once on app start) and not each time you call the constructor.Thanks for the explanation! Coming from a java background I confused the possibility to initialize at compile-time with the java-style initialization.
Sep 26 2011
On Sunday, September 25, 2011 23:40:36 Christian K=C3=B6stlin wrote:I have this small program, which does some data handling with structs=:=20 struct App { private int[] fData; this(size_t initialSize) { fData =3D new int[initialSize]; } void put(int i) { fData[0] =3D i; } int[] get() { return fData; } } =20 struct Builder { int i; App app =3D App(2); this(int i_) { i =3D i_; // app =3D App(2); } void put(int v) { app.put(v); } int[] get() { return app.get(); } } =20 int[] get(int i) { auto b =3D Builder(i); b.put(i); return b.get(); } =20 =20 unittest { =20 auto h1 =3D get(1); auto h2 =3D get(2); assert(h1[0] =3D=3D 1); assert(h2[0] =3D=3D 2); } =20 int main(string[] args) { return 0; } =20 compiling this with dmd -unittest shows, that the tests are failing. if you comment in the line // app =3D App(2); then the tests work =asexpected. Could you please explain what struct Builder { App app =3D App(2); } =doesexactly compared to doing thins in the structs constructor?It's a bug, but I don't know if it's that what you're trying to do does= n't=20 work or that it isn't illegal. When you directly initialize a member va= riable,=20 that initialization happens at compile time. The value of app in Builde= r.init=20 is what app is directly initialized to. So, if you set the value of app= in the=20 constructor to the same value that it was set to at compile time, it sh= ould=20 result in the same value for app. The problem is that App has a dynamic array in it, and that's allocated= on the=20 heap. Arrays can be used in CTFE, but I don't know if the same array al= located=20 in CTFE can then be used at runtime. If it can, then there's a bug here= ,=20 because app =3D App(2) in the constructor shouldn't be necessary. If it= can't,=20 then directly initializing an App at compile time shouldn't compile in = the=20 first place. - Jonathan M Davis
Sep 25 2011
On Monday, September 26, 2011 00:04:48 Andrej Mitrovic wrote:This should make things clearer for you: unittest { auto h1 = get(1); auto h2 = get(2); assert(h1 is h2); // both reference the same array } Field initialization is only done once (once per thread, or if a field is shared once on app start) and not each time you call the constructor.Ah. Yes. Okay. There isn't a bug here then (at least not in the compiler). The problem is that if you don't assign app in the constructor, it uses the exact same value as is in App.init - there is no copying going on - so every instance (or at least every instance on each thread) then points to exactly the same array. That's definitely something that could be easy to miss if you're not careful and is probably a sign that mutable arrays shouldn't generally be in the init property of structs (unless they're empty). - Jonathan M Davis
Sep 25 2011