【发布时间】:2013-02-17 10:34:34
【问题描述】:
我认为使用 emplace(c.end(),_1) 与 emplace_back(_1) 相同 但我不明白为什么语言设计者给出了两个功能而不是一个。 我假设我遗漏了一些信息。
那么 emplace(c.end(),_1) 和 emplace_back(_1) 的区别是什么?
【问题讨论】:
我认为使用 emplace(c.end(),_1) 与 emplace_back(_1) 相同 但我不明白为什么语言设计者给出了两个功能而不是一个。 我假设我遗漏了一些信息。
那么 emplace(c.end(),_1) 和 emplace_back(_1) 的区别是什么?
【问题讨论】:
与emplace相比,vector::emplace_back和deque::emplace_back对容器value_type的要求降低了。
仅代表vector 和deque:
除了EmplaceConstructible来自args;
emplace 需要 MoveInsertable 和 MoveAssignable,而
emplace_back 只需要MoveInsertable。
对于大多数分配器,包括std::allocator,MoveInsertable 与MoveConstructible 相同。
因此,如果您有一个类型要放入vector 或deque,它是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 不知道您提供给它的迭代器是 end 迭代器。
就是这样。
【讨论】:
insert() 和 push_back() 我猜也是一样。