www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Resizing array of classes

reply "m0rph" <m0rph.mailbox gmail.com> writes:
Suppose I have a dynamic array of classes, something like:

class Foo {
     int value;
}

Foo[] a;

Now I want to resize it and initialize new items with default 
values, so I do following:

a.length = 10;
a[0].value = 1;

And by executing the last line of code I've got a segmentation 
fault. Apparently a.length = 10 resizes array and creates 10 
references to Foo, but objects of Foo were not created. Do I need 
to manually iterate over new items of the array and explicitly 
call a[i] = new Foo, or there is a better (automatic) way?
Oct 19 2012
next sibling parent reply Marco Leise <Marco.Leise gmx.de> writes:
Am Fri, 19 Oct 2012 11:09:42 +0200
schrieb "m0rph" <m0rph.mailbox gmail.com>:

 Suppose I have a dynamic array of classes, something like:
 
 class Foo {
      int value;
 }
 
 Foo[] a;
 
 Now I want to resize it and initialize new items with default 
 values, so I do following:
 
 a.length = 10;
 a[0].value = 1;
 
 And by executing the last line of code I've got a segmentation 
 fault. Apparently a.length = 10 resizes array and creates 10 
 references to Foo, but objects of Foo were not created. Do I need 
 to manually iterate over new items of the array and explicitly 
 call a[i] = new Foo, or there is a better (automatic) way?

When you extend the length of an array, it is filled with the static .init value for the type, which is null here. I think you'll have to create the objects manually. foreach (ref foo; a) foo = new Foo; -- Marco
Oct 19 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-10-19 11:42, Marco Leise wrote:

 When you extend the length of an array, it is filled with
 the static .init value for the type, which is null here. I
 think you'll have to create the objects manually.

 foreach (ref foo; a) foo = new Foo;

Is this possible: a[] = new Foo; ? -- /Jacob Carlborg
Oct 19 2012
prev sibling next sibling parent Artur Skawina <art.08.09 gmail.com> writes:
On 10/19/12 11:09, m0rph wrote:
 Suppose I have a dynamic array of classes, something like:
 
 class Foo {
     int value;
 }
 
 Foo[] a;
 
 Now I want to resize it and initialize new items with default values, so I do
following:
 
 a.length = 10;
 a[0].value = 1;
 
 And by executing the last line of code I've got a segmentation fault.
Apparently a.length = 10 resizes array and creates 10 references to Foo, but
objects of Foo were not created. Do I need to manually iterate over new items
of the array and explicitly call a[i] = new Foo, or there is a better
(automatic) way?

Having it done implicitly by the language would be bad, but it's easy enough to automate: struct ObjArr(T, alias TF) { T[] array; alias array this; property: auto length() { return array.length; } auto length(size_t l) { auto old = array.length; array.length = l; for(; old<l; ++old) array[old] = TF(); return l; } } class Foo { int value; } void main() { ObjArr!(Foo, function { return new Foo; }) a; a.length = 10; a[0].value = 1; // And if you think the above declaration is too verbose: alias ObjArr!(Foo, function { return new Foo; }) FooArr; // then: FooArr b; b.length = 10; b[0].value = 1; } etc artur
Oct 19 2012
prev sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Friday, 19 October 2012 at 13:41:53 UTC, Jacob Carlborg wrote:
 On 2012-10-19 11:42, Marco Leise wrote:

 When you extend the length of an array, it is filled with
 the static .init value for the type, which is null here. I
 think you'll have to create the objects manually.

 foreach (ref foo; a) foo = new Foo;

Is this possible: a[] = new Foo; ?

Technically, it will compile and work, but you need to understand what it is actually going to do: It will allocate a single new Foo, and then assign that class reference to each and every index in your array. They will effectively all point to the same instance, rather than each to their own.
Oct 19 2012