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

Почему `std:: initializer_list` часто передается по значению?

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

http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/

нужно передать значение, если нужно сделать копию переданного объекта. Но копирование std::initializer_list не является хорошей идеей, поскольку

Копирование std::initializer_list не копирует базовые объекты. Базовый массив не может существовать после жизни исходный объект списка инициализатора закончился.

Итак, почему экземпляр его часто передается по значению, а не, скажем, const&, который гарантированно не делает ненужную копию?

4b9b3361

Ответ 1

Его прошло по значению, потому что его дешево. std::initializer_list, являющийся тонкой оболочкой, скорее всего, реализуется как пара указателей, поэтому копирование (почти) столь же дешево, как передача по ссылке. Кроме того, они фактически не выполняли копию, как правило, выполняли переход, так как в большинстве случаев аргумент строится из временного в любом случае. Однако это не влияет на производительность - перемещение двух указателей так же дорого, как их копирование.

С другой стороны, доступ к элементам копии может быть более быстрым, поскольку мы избегаем одного дополнительного разыменования (ссылки).

Ответ 2

Вероятно, по тем же причинам итераторы почти всегда передаются по значению: копирование итератора считается "дешевым". В случае initializer_list существует также тот факт, что большинство экземпляров будут временными с тривиальными деструкторами, поэтому компилятор может построить их непосредственно там, где он помещает аргумент функции без копирования. Наконец, существует тот факт, что, как итераторы, вызываемая функция, вероятно, захочет изменить значение, а это значит, что ей пришлось бы скопировать ее локально, если бы она была передана ссылкой на const.

EDIT:

Просто для обобщения: стандартная библиотека делает предположение в целом, что лучше передавать итераторы, initializer_lists и функциональные объекты по значению. В результате вы должны убедиться, что любые итераторы, iterator_lists или функциональные объекты, которые вы разрабатываете, дешевы для копирования, и вы должны принять в своем собственном коде, что они дешевы для копирования. Традиционное правило о том, когда использовать ссылки на const и когда использовать значение, должно, вероятно, быть изменено, чтобы отразить это:

Использовать pass по ссылке на const для типов классов, отличных от итераторов, initializer_lists или функциональных объектов; в противном случае используйте pass по значению.