考虑以下两种方法将元素附加到向量
中std::vector<int> vi1(10,42), vi2;
vi2.insert(vi2.end(),vi1.begin(),vi1.end());
<OR>
std::copy(vi1.begin(),vi1.end(),std::back_inserter(vi2));
std::copy
版本看起来更干净,我不必两次输入vi2
。但由于它是一个通用算法,而insert是一个成员函数,insert
可以比std::copy
表现更好还是做同样的事情?
我可以自己做基准,但我必须为每个模板类型的每个向量执行此操作。有人做过吗?
答案 0 :(得分:6)
有一些微妙的差异。在第一种情况下(std::vector<>::insert
),您为容器提供了一个范围,因此它可以计算距离并执行单个分配器以增长到最终所需的大小。在第二种情况(std::copy
)中,信息不直接出现在接口中,并且可能导致缓冲区的多次重新分配。
请注意,即使需要多次重新分配,插入的摊销成本仍必须保持不变,因此这并不意味着渐近的成本变化,但可能很重要。还要注意,库的一个特别智能的实现具有所有必需的信息,通过专门处理std::copy
的行为来专门处理反向插入迭代器,使第二个版本变得高效(尽管我还没有检查任何实现是否实际执行此操作)。
答案 1 :(得分:1)
vector::insert
可能会表现得更好。原因是vector
对象具有当前分配的内存缓冲区的内部知识,并且可以预先分配足够的内存来执行整个插入,因为可以使用随机访问迭代器预先计算元素的数量。但是,std::copy
和std::back_inserter
会一直调用vector::push_back
,这可能会触发多次分配。
例如,如果迭代器类别为std::vector::insert
,则libstdc ++中的RandomAccessIterator
的GNU实现会预先分配缓冲区。对于输入迭代器,vector::insert
可能等同于std::copy
,因为您无法提前确定元素数。
答案 2 :(得分:1)
你会认为vector::insert
可能能够优化一次插入多个项目的情况,但它比它看起来更难。如果迭代器是输出迭代器,那会怎么样 - 没有办法提前知道你要做多少次插入。 insert
的代码可能只有多个push_back
与back_inserter
相同。
答案 3 :(得分:0)
它不等同于std::copy
。它相当于push_back
(在某种意义上)。
是的,std::back_inserter
执行与std::copy
相同的操作,如果您使用std:front_inserter
,也可以在前面插入(尽管您不能与std::vector
)一起使用。如果您使用std::inserter
,它也可以在指定的迭代器中插入。所以你看,std::copy
基于你作为第三个参数传递的内容做了什么。
现在回到问题的本质。我认为你应该使用insert
,因为它可以更好地执行,因为它可能会发现要插入的元素的数量,因此它可以一次分配那么多内存(如果需要的话) )。在您的情况下,它可能会表现更好,因为v1
是std::vector
,这意味着在O(1)时间内很容易计算元素的数量。