Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
September 25, 2011 confusion about structs | ||||
---|---|---|---|---|
| ||||
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 |
September 25, 2011 Re: confusion about structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Christian Köstlin | 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. |
September 25, 2011 Re: confusion about structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Christian Köstlin | On Sunday, September 25, 2011 23:40:36 Christian Köstlin wrote:
> 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?
It's a bug, but I don't know if it's that what you're trying to do doesn't work or that it isn't illegal. When you directly initialize a member variable, that initialization happens at compile time. The value of app in Builder.init is what app is directly initialized to. So, if you set the value of app in the constructor to the same value that it was set to at compile time, it should result in the same value for app.
The problem is that App has a dynamic array in it, and that's allocated on the heap. Arrays can be used in CTFE, but I don't know if the same array allocated in CTFE can then be used at runtime. If it can, then there's a bug here, because app = App(2) in the constructor shouldn't be necessary. If it can't, then directly initializing an App at compile time shouldn't compile in the first place.
- Jonathan M Davis
|
September 26, 2011 Re: confusion about structs | ||||
---|---|---|---|---|
| ||||
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
|
September 26, 2011 Re: confusion about structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | 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.
|
Copyright © 1999-2021 by the D Language Foundation