Подтвердить что ты не робот

Зачем использовать initializer_list вместо vector в параметрах?

Какова фактическая польза и цель initializer_list, для неизвестного количества параметров? Почему бы просто не использовать vector и сделать с ним?

На самом деле это звучит как просто vector с другим именем. Зачем беспокоиться?

Единственное "преимущество", которое я вижу в initializer_list, состоит в том, что оно имеет элементы const, но это, по-видимому, не является достаточной причиной для создания всего этого нового типа. (Вы можете просто использовать const vector в конце концов.)

Итак, что я вижу?

4b9b3361

Ответ 1

Это своего рода контракт между программистом и компилятором. Программист говорит {1,2,3,4}, и компилятор создает из него объект типа initializer_list<int>, содержащий ту же последовательность элементов в нем. Этот контракт является требованием, заданным спецификацией языка в реализации компилятора.

Это означает, что программист не создает вручную такой объект, но это компилятор, который создает объект, и передает этот объект функции, который принимает initializer_list<int> как аргумент.

Реализация std::vector использует этот контракт и поэтому определяет конструктор, который принимает initializer_list<T> в качестве аргумента, так что он может инициализировать себя элементами в списке инициализаторов.

Теперь предположим какое-то время, что std::vector не имеет конструктора, который принимает std::initializer_list<T> в качестве аргумента, тогда вы получите следующее:

 void f(std::initializer_list<int> const &items);
 void g(std::vector<int> const &items);

 f({1,2,3,4}); //okay
 g({1,2,3,4}); //error (as per the assumption)

В соответствии с предположением, поскольку std::vector не имеет конструктора, который принимает std::initializer_list<T> как аргумент, из которого следует, что вы не можете передать {1,2,3,4} в качестве аргумента в g(), как показано выше, поскольку компилятор не может создать экземпляр из std::vector из выражения {1,2,3,4} напрямую. Это связано с тем, что такой контракт никогда не заключен между программистом и компилятором и не навязывается языком. Через std::initializer_list std::vector может создать себя из выражения {1,2,3,4}.

Теперь вы поймете, что std::initializer_list можно использовать везде, где вам нужно выражение формы {value1, value2, ...., valueN}. Именно поэтому другие контейнеры из библиотеки Standard также определяют конструктор, который принимает std::initializer_list как аргумент. Таким образом, никакой контейнер не зависит от какого-либо другого контейнера для построения из выражений формы {value1, value2, ...., valueN}.

Надеюсь, что это поможет.

Ответ 2

Ну, std::vector должен использовать initializer_list, чтобы получить этот синтаксис, поскольку он явно не может использовать себя.

В любом случае initializer_list должен быть очень легким. Он может использовать оптимальное место хранения и предотвращать ненужные копии. С помощью vector вы всегда будете получать распределение кучи и имеете хорошие шансы получить больше копий/ходов, чем хотите.

Кроме того, синтаксис имеет очевидные отличия. Одна из таких вещей - вычитание типа шаблона:

struct foo {
    template<typename T>  
    foo(std::initializer_list<T>) {}
};

foo x{1,2,3}; // works

vector здесь не работает.

Ответ 3

Самое большое преимущество initializer_list over vector заключается в том, что он позволяет указать на месте определенную последовательность элементов, не требуя посвятить обработку для создания этого списка.

Это избавит вас от необходимости настраивать несколько вызовов на push_back (или цикл for) для инициализации vector, даже если вы точно знаете, какие элементы будут вставляться в вектор.

Фактически, vector сам имеет конструктор, принимающий initializer_list для более удобной инициализации. Я бы сказал, что два контейнера дополняют друг друга.

// v is constructed by passing an initializer_list in input
std::vector<std::string> v = {"hello", "cruel", "world"};

Конечно, важно знать, что initializer_list имеет некоторые ограничения (сужение конверсий не допускается), что может сделать его неприемлемым или невозможным использовать в некоторых случаях.