我认为使用 emplace(c.end(),_1) 与 emplace_back(_1) 相同,但我不明白为什么语言设计者提供了两个功能而不是一个。我假设我遗漏了一些信息。
那么 emplace(c.end(),_1) 与 emplace_back(_1) 的区别是什么?
最大的区别是对容器的要求value_type
相对于.vector::emplace_back
deque::emplace_back
emplace
vector
只为deque
:
除了EmplaceConstructible
来自args
;
emplace
需要MoveInsertable
和MoveAssignable
,而
emplace_back
只需要MoveInsertable
.
对于大多数分配器,包括std::allocator
,MoveInsertable
与 相同MoveConstructible
。
因此,如果您有一个类型要放入vector
ordeque
中,它是MoveConstructible
,但不是MoveAssignable
,emplace_back
是您的朋友。它也可能会稍微快一些,并且代码大小会稍微小一些,但这是一个实现质量问题(标准不保证)。并且差异可能比您注意到的要小(除非仔细测量)。
例如,给定:
#include <vector>
struct A
{
A() = default;
A(A&&) = default;
A& operator=(A&&) = delete;
};
这编译:
int main()
{
std::vector<A> v;
v.emplace_back();
}
但这不会:
int main()
{
std::vector<A> v;
v.emplace(v.end()); // error A is not MoveAssignable
}
但是,如果我改变:
A& operator=(A&&) = delete;
至:
A& operator=(A&&) = default;
那么这两个例子都会编译(并运行良好)。
根据数据结构,可能emplace_back
比emplace(c.end(), _1)
. 例如,使用std::vector
,emplace_back
不必检查哪些(如果有)元素需要移动,从而emplace_back
稍微快一点。
是的,在那种情况下它们是等价的。
emplace
更通用,因为它不仅在最后起作用;emplace_back
很方便,因为您不必编写c.end()
.
实现也可能有好处——回想一下,emplace
不知道您提供给它的迭代器是结束迭代器。
而已。