Почему пустой вектор вызывает конструктор значения по умолчанию? - PullRequest
29 голосов
/ 27 июня 2011

Используя g ++, я замечаю, что создание вектора нулевого размера вызывает конструктор параметризованного типа объекта вектора один раз. Затем он удаляется. Почему это происходит?

#include <iostream>
#include <vector>
using namespace std;

class s
{
    public:
    s() { cout << endl << "default s constructor" << endl; }
    ~s() { cout << endl << "default s destructor" << endl; }

};

int main()
{
    vector<s> v(0);
}

Выход:

конструктор по умолчанию

деструктор по умолчанию

Ответы [ 2 ]

29 голосов
/ 27 июня 2011

Поскольку вы явно передаете начальный размер, который вызывает конструктор с другим параметром, значение по умолчанию которого равно s(). Просто пропустите (0) (т.е. std::vector<s> v;), и этого не произойдет.

Для полноты, Стандарт 23.2.4-2 определяет конструктор, который вы вызываете:

explicit vector(size_type n, const T& value =T(),
const Allocator& = Allocator());

В сторону (относится к C ++ 03, но не к C ++ 11)

Еще один интересный поведенческий аспект этого конструктора также поднимает голову над С.О. периодически: когда начальное количество запрошенных элементов> 0, оно копирует эти элементы из параметра prototypal в конструктор:

  • люди часто помещают конструктор по умолчанию, который не инициализирует переменные-члены, надеясь сделать vector(n) почти так же быстро, как и основное свободное хранилище, НО
  • конструктор копирования по-прежнему вызывается n раз для копирования "мусорного" содержимого объекта-прототипа в каждый из запрошенных элементов

Это имеет очевидные затраты производительности, но также может привести к сбою приложения , если содержимое мусора включает, например, указатели, которые копи-конструктор может только предположить, являются действительными. Точно так же это даже очень опасно даже для push_back такого неинициализированного мусорного объекта - в нем отсутствует семантическая инкапсуляция с надлежащим значением, и его можно копировать при изменении размера вектора, над вектором выполняются алгоритмические операции, такие как std::sort() и т. Д.

10 голосов
/ 27 июня 2011

Фактический конструктор, который вы вызываете (из cplusplus.com):

explicit vector ( size_type n, const T& value= T(), const Allocator& = Allocator() );

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

...