【发布时间】:2014-12-06 02:30:51
【问题描述】:
据我所知,std::back_inserter 在 STL 算法中工作的任何地方,您都可以传递一个由 .end() 构造的 std::inserter:
std::copy(l.begin(), l.end(), std::back_inserter(dest_list));
std::copy(l.begin(), l.end(), std::inserter(dest_list, dest_list.end()));
并且,与back_inserter 不同,据我所知inserter 适用于任何 STL 容器!我为std::vector、std::list、std::map、std::unordered_map尝试了成功,然后惊讶地来到这里。
我认为这可能是因为 push_back 对于某些结构可能比 insert(.end()) 更快,但我不确定...
std::list 似乎并非如此(有道理):
// Copying 10,000,000 element-list with std::copy. Did it twice w/ switched order just in case that matters.
Profiling complete (884.666 millis total run-time): inserter(.end())
Profiling complete (643.798 millis total run-time): back_inserter
Profiling complete (644.060 millis total run-time): back_inserter
Profiling complete (623.151 millis total run-time): inserter(.end())
但它对std::vector 有点影响,虽然我不太确定为什么?:
// Copying 10,000,000 element-vector with std::copy.
Profiling complete (985.754 millis total run-time): inserter(.end())
Profiling complete (746.819 millis total run-time): back_inserter
Profiling complete (745.476 millis total run-time): back_inserter
Profiling complete (739.774 millis total run-time): inserter(.end())
我猜想在向量中找出迭代器的位置然后在其中放置一个元素而不是 arr[count++] 会稍微多一些开销。也许是这样?
但是,这还是主要原因吗?
我想我的后续问题是“可以为模板函数编写 std::inserter(container, container.end()) 并期望它(几乎)适用于任何 STL 容器吗?”
我在迁移到标准编译器后更新了这些数字。这是我的编译器的详细信息:
gcc 版本 4.8.2 (Ubuntu 4.8.2-19ubuntu1)
目标:x86_64-linux-gnu
我的构建命令:
g++ -O0 -std=c++11 algo_test.cc
我认为this question asks the second half of my question,即“我可以编写一个使用std::inserter(container, container.end()) 的模板函数并期望它几乎适用于每个容器吗?”
答案是“是的,除了std::forward_list 之外的每个容器。”但是根据下面 cmets 和user2746253 的回答中的讨论,听起来我应该知道std::vector 比使用std::back_inserter 慢...
因此,我可能希望使用RandomAccessIterators 专门针对容器模板使用back_inserter。那有意义吗?谢谢。
【问题讨论】:
-
back_inserter_iterator调用push_back,所以它当然不适用于所有容器。另一方面,insert_iterator调用insert。这些操作的速度取决于您要执行的操作。works for ANY STL container!!是错误的。也许C++ vector's insert & push_back difference 会提供信息。 -
例如
std::queue -
这两者有不同的要求和保证。例如,
std::vector<T>的inserter要求T是 MoveAssignable,back_inserter不是。 Live example -
如果您要衡量性能,请不要使用
-O0。 -
@BenVoigt:
std::queue不是容器,而是容器适配器;例如,它甚至没有begin()和end()。
标签: c++ vector stl iterator containers