Метод 1 может извлечь выгоду из исключения копирования, но следующий очень похожий код не может:
ItemContainer a = CreateManyItems();
// do some stuff with a
a = CreateManyItems();
// do some different stuff with a
Для этого требуется семантика перемещения C ++ 0x, чтобы эффективно избежать копирования контейнера.Когда вы разрабатываете свою функцию, вы не знаете, как клиенты захотят ее использовать, поэтому, полагаясь на элиминацию копирования, вы можете поймать кого-то с неприятным падением производительности.Их исправление в C ++ 03 будет следующим, и они должны быть готовы к ситуациям, в которых они нуждаются:
ItemContainer a = CreateManyItems();
// do some stuff with a
CreateManyItems().swap(a);
Поскольку это в основном то же самое, что и метод 2, вы можете предложить оба варианта: 1 * 1007.* и 2, как перегрузки, которые намекают вызывающей стороне, что они должны подумать о потенциальной ловушке производительности.
При условии, что элементы в коллекции не ссылаются друг на друга, моя предпочтительная формаAPI выглядит следующим образом, но это зависит от того, какой интерфейс вы предоставляете - поскольку это шаблон, реализация должна быть доступна при компиляции вызывающей стороны (если вы не можете заранее предсказать типы, с которыми она будет использоваться, и extern
эти специализации):
template <typename OutputIterator>
void CreateManyItems(OutputIterator out) {
*out++ = foo; // for each item "foo"
}
ItemContainer a;
CreateManyItems(std::back_inserter(a));
// do some stuff with a
a.clear();
CreateManyItems(std::back_inserter(a));
Теперь, если вызывающая сторона предпочла бы иметь элементы в deque, потому что они хотят произвольный доступ, то им просто нужно настроить свой код:
std::deque<Item> a;
CreateManyItems(std::back_inserter(a));
Или, если они вообще не нужны в коллекции, они могли бы написать алгоритм потоковой передачи, который выполняет свою работу в своем итераторе вывода, и сэкономить многопамяти.
Вместо этого вы могли бы написать класс итератора, который генерирует элементы один за другим, но приводит к тому, что становится немного более нервным, поскольку поток управления "наизнанку", ине обязательно делает код вызывающего абонента более приятным (свидетель istream_iterator
).