std::vector::emplace_back 比 std::vector::push_back 慢的示例?
Posted
技术标签:
【中文标题】std::vector::emplace_back 比 std::vector::push_back 慢的示例?【英文标题】:Examples where std::vector::emplace_back is slower than std::vector::push_back? 【发布时间】:2015-10-05 05:14:02 【问题描述】:我目前正在阅读 Scott Meyer 的“Effective Modern C++”。在第 42 项中,他声称,例如std::vector::emplace_back
通常(但并非总是)与使用 push_back
一样快,甚至更快。他列出了三个条件至少应该一样快,但在这些条件不完全满足的情况下没有提供反例。
有人可以给我举个例子,使用emplace_back
会导致性能比使用push_back
更差吗?
【问题讨论】:
这不是一回事,但你不能将emplace_back
用于大括号初始化程序(例如,调用像vecOfVecs.emplace_back(1, 2, 3);
这样的列表构造函数),所以我想这不会像快到push_back
。
He lists three conditions
是?
如果emplace_back
实际上是更慢,那将是一个非常模糊和奇怪的情况。它通常相同或更好。
Scott Meyers 在 @Meeting C++ 2014 here 的主题演讲中提到了这个确切的问题。享受吧。
【参考方案1】:
这取决于您所说的“emplace_back
比 push_back
慢”的意思。考虑构建成本高且复制成本低的类,例如具有写入时复制行为的类,或表示哈希值的类:
class Hash
public:
int value;
Hash(const char *data) : value(very_expensive_hash_function(data)) // expensive
Hash(const Hash &other) : value(other.value) // cheap
;
Hash h(foo);
std::vector<Hash> v;
v.push_back(h); // 1
v.emplace_back("foo"); // 2
那么,(1) 确实会比 (2) 快。然而,这样的比较是不公平的。在比较性能时,应考虑所涉及的构造函数的成本。
【讨论】:
【参考方案2】:愚蠢的例子:
std::vector<always_throws_on_construction> vec;
if(vec.size() == vec.capacity())
vec.push_back(always_throws_on_construction());
可能会比
更快std::vector<always_throws_on_construction> vec;
if(vec.size() == vec.capacity())
vec.emplace_back();
【讨论】:
猜测的理由是什么? @black 在推回的情况下,您在运行任何向量代码之前抛出异常。在 emplace 后部案例中,您动态扩展向量以能够处理新元素然后抛出。就像我说的,这是一个愚蠢的例子。 [编辑清楚抛出异常] 哦,是的。出于某种原因,我认为你说的相反,这就是我问的原因。【参考方案3】:基本上这归结为标准实现。从理论上讲,emplace 应该总是一样快或更快,但现实情况是没有标准库实现充分利用这一点。
几年前他就这个问题发表过演讲:https://www.youtube.com/watch?t=3427&v=smqT9Io_bKo
查看演讲的前 1 小时,了解更详细的说明。谈话结束时的问答也很重要。
【讨论】:
以上是关于std::vector::emplace_back 比 std::vector::push_back 慢的示例?的主要内容,如果未能解决你的问题,请参考以下文章