Почему конструктор C ++ должен использовать динамическое размещение для массива? - PullRequest
2 голосов
/ 18 июля 2011

В моих примечаниях к курсу приведены эти два примера.По-видимому, первый не разрешен, есть ли техническая причина, по которой я не могу разместить в стеке?Или это стандарт C ++?

   // Constructor may force dynamic allocation when initializating an array of objects.

   Complex ac[10];             // complex array initialized to 0.0
    for ( int i = 0; i < 10; i += 1 ) {
         ac[i] = (Complex){ i, 2.0 } // disallowed
    }


    // MUST USE DYNAMIC ALLOCATION
    Complex *ap[10];            // array of complex pointers
    for ( int i = 0; i < 10; i += 1 ) {
         ap[i] = new Complex( i, 2.0 ); // allowed
    }

Ответы [ 5 ]

7 голосов
/ 18 июля 2011

Первый неверный синтаксис. Но если предположить, что у вашего Complex класса есть общедоступный оператор присваивания копии (неявный, вероятно, должен подойти), то следующее должно подойти:

Complex ac[10];             // complex array initialized to 0.0
for ( int i = 0; i < 10; i += 1 ) {
     ac[i] = Complex( i, 2.0 );
}
6 голосов
/ 18 июля 2011

Видимо первый не разрешен

Верно, но только потому, что в нем используется неправильный синтаксис. Следующие работы:

ac[i] = Complex(i, 2.0);

Таким образом, утверждение на самом деле неверно (при условии, что Complex может быть назначено, что по умолчанию может) - динамическое распределение не требуется.

2 голосов
/ 18 июля 2011

Следующее абсолютно допустимо - у вас просто неправильный синтаксис.Вы не можете создавать списки инициализаторов, но вы можете вызывать конструкторы, как если бы они были функциями.

Complex ac[10];  // calls default constructor for each element
for ( int i = 0; i < 10; i += 1 ) {
     ac[i] = Complex(i, 2.0);  // constructs a temporary,
                               // then uses the assignment operator
}
1 голос
/ 18 июля 2011

Вы, конечно, можете предоставить все значения в списке инициализатора, например

Complex ac[] = { Complex(0, 2.0), Complex(1, 2.0), /* and so on */ };

но это становится очень громоздким очень быстро по мере увеличения размера. Поэтому естественно использовать цикл.

Хотя не представляется возможным независимо инициализировать элементы в автоматическом (который обычно эквивалентен «в стеке») буфере, это совсем не просто.

Проблема в том, что определение массива вызывает немедленный вызов конструктора. Вы должны будете определить массив char (у которого нет конструктора), а затем создать и уничтожить элементы вручную (используя новые и явные вызовы деструктора). Это не так сложно, если только вам не нужна безопасность исключений, и в этом случае угловые случаи очень сложны в обращении.

Если вам разрешено конструировать по умолчанию, а затем переназначать элементы, это легко, и это покрыто другими ответами. Если у Complex есть рабочий оператор присваивания, вы должны сделать это.

0 голосов
/ 18 июля 2011

Нет такого правила, что конструктор должен иметь динамическое выделение для массива.

ac[i] = Complex( i, 2.0 );

допустимо.На самом деле вы должны избегать динамических массивов, насколько это возможно.

...