如果您需要尽可能轻量级的解决方案,我建议使用基于迭代器/基于回调的方法。
原因是它将供应商与消费者的使用模式分离。
特别是,将结果放入集合1(即使结果可能“优化” - 可能进入 (N)RVO 或移动而不是复制对象)仍然会为全部容量分配一个完整的容器。
编辑:1对“必修论文”的极好补充(它们不是;如果您想了解事物,它们会非常有帮助):想要速度吗?通过戴夫亚伯拉罕的价值。
现在
如果消费者在前几个元素之后实际上停止处理数据,这将是矫枉过正
for(auto f=myType.begin(), l=myType.end(); f!=l; ++f)
{
if (!doProcessing(*f))
break;
}
即使消费者最终处理所有元素,这也可能不是最理想的:可能不需要在任何特定时刻复制所有元素,因此可以重用“当前元素”的“插槽”,减少内存需求,增加缓存地方性。例如:
for(auto f=myType.begin(), l=myType.end(); f!=l; ++f)
{
myElementType const& slot = *f; // making the temp explicit
doProcessing(slot);
}
请注意,如果消费者 确实想要一个包含所有元素的集合,迭代器接口仍然是优越的:
std::vector<myElementType> v(myType.begin(), myType.end());
// look: the client gets to _decide_ what container he wants!
std::set<myElementType, myComparer> s(myType.begin(), myType.end());
尝试以其他方式获得这种灵活性。
最后,还有一些风格元素:
从本质上讲,使用迭代器很容易公开(const)对元素的引用;这使得避免对象切片和使客户端能够以多态方式使用元素变得更加容易。
可以重载迭代器样式接口以在取消引用时返回非常量引用。要返回的容器,不能包含引用(直接)
如果您遵守 C++11 中基于范围的要求,您可以使用一些语法糖:
for (auto& slot : myType)
{
doProcessing(slot);
}
最后,(如上所示),一般意义上的迭代器可以很好地与标准库一起工作。
回调样式(以及类似的输出迭代器样式)具有迭代器样式的许多优点(即,您可以使用返回值中途中止迭代,并且您可以在不预先分配所有元素的副本的情况下进行处理),但是在我看来,使用起来不太灵活。当然,在某些情况下,您可能希望鼓励一种特定的使用模式,这可能是一个不错的方法。