Интернет, компьютеры, софт и прочий Hi-Tech

Подписаться через RSS2Email.ru

Страница 5 из 10 - Предыдущая - Следующая
Все страницы - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10

Краткий FAQ по C++

[10.5] Какой конструктор будет вызван, если я создаю массив объектов типа Fred?

Конструктор по умолчанию [10.4] для класса Fred (за исключением случая, описанного ниже)

Не существует способа заставить компилятор вызвать другой конструктор (за исключением способа, описанного ниже). Если у вашего класса Fred нет конструктора по умолчанию [10.4], то при попытке создания массива объектов типа Fred вы получите ошибку при компиляции.

    class Fred {
    public:
      Fred(int i, int j);
      // ... предположим, что для класса Fred нет конструктора по умолчанию
      // [10.4]...
    };

    int main()
    {
      Fred a[10];               // ОШИБКА: У Fred нет конструктора по умолчанию
      Fred* p = new Fred[10];   // ОШИБКА: У Fred нет конструктора по умолчанию
    }

Однако если вы создаете, пользуясь STL [32.1], vector<Fred> вместо простого массива (что вам скорее всего и следует делать, поскольку массивы опасны [21.5]), вам не нужно иметь конструктор по умолчанию в классе Fred, поскольку вы можете задать объект типа Fred для инициализации элементов вектора:

    #include <vector>
    using namespace std;

    int main()
    {
      vector<Fred> a(10, Fred(5,7));
      // Десять объектов типа Fred
      // будут инициализированы Fred(5,7).
      // ...
    }

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

    class Fred {
    public:
      Fred(int i, int j);
    // ... предположим, что для класса Fred
    // нет конструктора по умолчанию [10.4]...
    };

    int main()
    {
      Fred a[10] = {
        Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7),
        Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7)
      };

      // Десять объектов массива Fred
      // будут инициализированы Fred(5,7).
      // ...
    }

Конечно, вам не обязательно использовать Fred(5,7) для каждого элемента. Вы можете использовать любые числа или даже параметры и другие переменные. Суть в том, что такая запись (a) возможна, но (б) не так хороша, как запись для вектора. Помните: массивы опасны [21.5]. Если вы не вынуждены использовать массивы - используйте вектора.

[10.6] Должны ли мои конструкторы использовать "списки инициализации" или "присваивания значений"?

Конструкторы должны инициализировать все члены в списках инициализации.

Например, пусть конструктор инициализирует член x_, используя список инициализации: Fred::Fred() : x_(какое-то-выражение) { }. С точки зрения производительности важно заметить, что какое-то-выражение не приводит к созданию отдельного объекта для копирования его в x_: если типы совпадают, то какое-то-выражение будет создано прямо в x_.

Напротив, следующий конструктор использует присваивание: Fred::Fred() { x_ = какое-то-выражение; }. В этом случае какое-то-выражение приводит к созданию отдельного временного объекта, который потом передается в качестве параметра оператору присваивания объекта x_, а потом уничтожается при достижении точки с запятой. Это неэффективно.

Есть и еще один источник неэффективности: во втором случае (с присваиванием) конструктор по умолчанию для объекта (неявно вызванный до { тела конструктора) мог, например, выделить по умолчанию некоторое количество памяти или открыть файл. Вся эта работа окажется проделанной впустую, если какое-то-выражение и/или оператор присваивания привели к закрытию этого файла и/или освобождению памяти (например, если конструктор по умолчанию выделил недостаточно памяти или открыл не тот файл).

Выводы: при прочих равных условиях ваш код будет более быстрым, если вы используете списки инициализации, а не операторы присваивания.

Страница 5 из 10 - Предыдущая - Следующая

Биржа долевых инвестиций SIMEX.

Последнее редактирование: 2009-10-02 16:11:42

Метки материала: C++, FAQ, программирование, конструкторы, списки инициализации, присваивание значений, инициализация, присваивание, массив, объекты, конструктор по умолчанию, компилятор, вектор, производительность, оператор присваивания, явная инициализация

Оставьте, пожалуйста, свой комментарий к публикации

Представиться как     Антибот:
   

Просьба не постить мусор. Если вы хотите потестить xBB, воспользуйтесь кнопкой предварительного просмотра на панели инструментов xBBEditor-а.


© 2007-2019, Дмитрий Скоробогатов.
Разрешается воспроизводить, распространять и/или изменять материалы сайта
в соответствии с условиями GNU Free Documentation License,
версии 1.2 или любой более поздней версии, опубликованной FSF,
если только иное не указано в самих материалах.