Method 1 can benefit from copy elision, but the following very similar code cannot:
ItemContainer a = CreateManyItems();
// do some stuff with a
a = CreateManyItems();
// do some different stuff with a
This requires C++0x move semantics in order to efficiently avoid copying the container. When you design your function, you don't know how clients are going to want to use it, so relying on copy elision in this way might catch someone out with an unpleasant performance hit. Their fix in C++03 would be as follows, and they should be alert to situations where they need it:
ItemContainer a = CreateManyItems();
// do some stuff with a
CreateManyItems().swap(a);
Since this is basically the same as Method 2, you could offer both 1 and 2, as overloads, which hints to the caller that they should think about a potential performance trap.
Provided that the Items in the collection don't refer to each other, my preferred form of the API is as follows, but it depends what kind of interface you're exposing - because it's a template the implementation must be available when the caller is compiled (unless you can predict in advance the types it will be used with and extern
those specializations):
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));
Now, if the caller would prefer to have the items in a deque, because they want random access, then they just need to tweak their code:
std::deque<Item> a;
CreateManyItems(std::back_inserter(a));
Or if they don't need them in a collection at all, they could write a streaming algorithm that does its work in their output iterator, and save a lot of memory.
You could instead write an iterator class that generates the Items one after another, but that tends to be a bit more fiddly because the control flow is "inside out", and doesn't necessarily make the callers code look any nicer (witness istream_iterator
).