Passing parameter when creating object array

Chris Nicholson-Sauls ibisbasenji at gmail.com
Tue Aug 7 14:24:06 PDT 2007


Chris Nicholson-Sauls wrote:
> Kirk McDonald wrote:
>> Chris Nicholson-Sauls wrote:
>>> James Dennett wrote:
>>>> Daniel White wrote:
>>>>> I've just found out from elsewhere that it's not possible in C++ to 
>>>>> create an array of objects whilst simultaneously passing a 
>>>>> parameter to the constructor of each of those objects. Something 
>>>>> like this returns an error:
>>>>>
>>>>> Myclass x (10)[50]
>>>>>
>>>>> I don't want to have to do:
>>>>>
>>>>> Myclass x[5] = {10,10,10,10,10,10.................}  // ...and so on
>>>>>
>>>>> Does D support the more intuitive Myclass x (10)[50] mechanism?
>>>>
>>>> C++ has a library type for arrays, where you can write
>>>>
>>>> std::vector<MyClass> x(50, MyClass(10));
>>>>
>>>> D tends to prefer pushing this kind of thing out of the library
>>>> and into the language, but maybe somebody can point out the D
>>>> library solution for this.
>>>>
>>>> -- James
>>>
>>> Its straightforward:
>>>
>>> T[] populateArray (T) (int len, lazy T ctor) {
>>>     T[] result = new T[len];
>>>
>>>     foreach (inout elem; result) {
>>>         elem = ctor();
>>>     }
>>>     return result;
>>> }
>>>
>>>
>>> Usage is like so:
>>>
>>> auto array = populateArray(50, new MyClass(10));
>>>
>>>
>>>
>>> This also works fine with structures, and technically any other type. 
>>> Although its inefficient for basic scalars, for that use a 
>>> slice-assignment:
>>>
>>> int[]   arr1 = new int[50]; arr1[] = 10;
>>> int[50] arr2;               arr2[] = 10;
>>>
>>>
>>> -- Chris Nicholson-Sauls
>>
>> Using new on a dynamic array type already allows you to pass something 
>> looking like a constructor call:
>>
>> auto a = new int[](50); // An array of 50 elements
>>
>> It might be appropriate to add a second, optional parameter to this 
>> constructor, with the array's default initializer:
>>
>> auto b = new int[](50, 5); // An array of 50 5s
>>
>> This implies that, for arrays of class references, saying this
>>
>> auto c = new Foo[](10, new Foo);
>>
>> would result in an array of 10 references to the same instance of Foo. 
>> I believe that any other behavior would be surprising.
>>
>> Therefore, some notation must be provided for allocating an array and 
>> not initializing its contents, which would allow something like your 
>> lazy initializer above to operate without initializing the array's 
>> contents first. A number of ideas occur to me; the simplest is perhaps 
>> an optional argument to 'new' itself:
>>
>> auto d = new(false) Foo[](10); // Allocate array, don't initialize it.
>>
>> All of this being said, I am not sure how serious of an issue this 
>> really is.
>>
> 
> Hmm.  That could be rather dangerous, actually.  So here's another 
> thought.  Let's get 'new int[5][10][15]' working, then redefine the 
> trailing parentheses to specify an initializor, and then furthermore 
> make that initializor lazy anytime it is more complex than a literal or 
> symbol, possibly including 'symbol.symbol' as field reads.
> 
> auto array = new MyClass[50](new MyClass(10));
> 
> You know, now that I actually see it... I'm not so fond of it.
> 
> But honestly, I don't think the cost is worth worrying too much about. I 
> ran a quick test timing my function above against a simple foreach over 
> an pre-allocated array.  The 'populate' function averaged only 10 
> microseconds slower.  I, for one, can handle 10 millionths of almost 
> anything.  :)
> 
> -- Chris Nicholson-Sauls

Oh yes, I should probably also mention that my test program was creating 
arrays of 1000 objects -- not just 50.  :)  So for use cases such as in 
the OP, the difference is utterly insignificant.

-- Chris Nicholson-Sauls


More information about the Digitalmars-d-learn mailing list