Thread overview
Resizing array of classes
Oct 19, 2012
m0rph
Oct 19, 2012
Marco Leise
Oct 19, 2012
Jacob Carlborg
Oct 19, 2012
monarch_dodra
Oct 19, 2012
Artur Skawina
October 19, 2012
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?

October 19, 2012
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

October 19, 2012
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
October 19, 2012
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
October 19, 2012
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.