2013-08-22 2 views
3

я наткнулся на код, как это от C++ reference page:Как можно построить std :: vector конструктивных объектов, не являющихся стандартными?

#include <algorithm> 
#include <list> 
#include <vector> 
#include <functional> 

int main() 
{ 
    std::list<int> l = {-4, -3, -2, -1, 0, 1, 2, 3, 4}; 
    std::vector<std::reference_wrapper<int>> v(l.begin(), l.end()); 
    return 0; 
} 

Это фрагмент из раздела «Примеры». Код компилируется и выполняется, как ожидалось. Но как это возможно? std::reference_wrapper<int> не является конструктивным по умолчанию. Как вы можете сделать std::vector этих вещей? Я всегда представлял std::vector как динамический массив. Но как вы можете инициализировать блок памяти, свежее заданный вам ОС, таким образом, от std::list?

Это может показаться запутанным вопросом, но по какой-то причине я не могу полностью понять, что происходит в коде выше. Что там происходит?

+0

Я всегда думал, что он был инициализирован нулевыми байтами, и если есть конструктор, поместите его. –

+0

Похоже, вы не можете добавить к этому виду вектор, но когда он строится, он вызывает конструкторы, не относящиеся к умолчанию, для каждого элемента в 'l', например' std :: reference (-4) ',' std: : reference (-3) ', etc ... –

+1

@Robl: Да, вы можете добавить к нему, используя любой метод, который не требует конструктора по умолчанию. –

ответ

2

Конструктор std::vector<> сначала получает блок сырой памяти соответствующего размера (с использованием его allocator). Затем он создает объекты. В случае конкретного конструктора здесь

template<typename It> 
std::vector::vector(It begin, It end); 

он создает элементы из ValueType из итераторы, таким образом, каждый reference_wrapper<int> построен (на месте) из int.

6

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

В приведенной ниже, к примеру, не будет работать:

std::vector<std::reference_wrapper<int>> v(42); 
+0

О, я вижу. Если я пишу класс шаблона, нормально ли для некоторых методов не работать для всех параметров типа шаблона? Является ли это хорошей практикой или это просто привилегия стандартной библиотеки? –

+3

@MartinDrozdik: возможно с некоторыми ограничениями. Пока метод не создается, тогда все в порядке; однако иногда метод может быть создан без запроса, например, метод 'virtual' всегда создается. –

1

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

Что касается реализации, то, это поведение может быть реализована путем выделения памяти с malloc вместо new (так что не конструктор не вызывается), а затем с помощью размещения new при добавлении элементов в векторе.

+0

Итак, это волшебство здесь. Я всегда думал, что std :: vector использует новый внутренний. Это имеет смысл. –

+0

@MartinDrozdik он может использовать 'new' внутри, но' new unsigned char [size * sizeof (T)] 'вместо' new T [size] '. – Yakk

Смежные вопросы