我认为使用template(c.end(),_1)与template_back(_1)相同但我不明白为什么语言设计者给出了两个函数而不是一个。我想我遗漏了一些信息。
那么,是什么区别了template(c.end(),_1)和template_back(_1)呢?
最大的区别是,与emplace
相比,vector::emplace_back
和deque::emplace_back
对容器value_type
的要求降低了。
仅针对vector
和deque
:
除了来自CCD_ 8的CCD_;
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
稍微快一点。
是的,在这种情况下它们是等价的。
CCD_ 27更为通用,因为它不仅仅在末尾起作用;emplace_back
很方便,因为您不必编写c.end()
。
实施也可能带来好处;回想一下,emplace
不知道您提供给它的迭代器是端迭代器。
就是这样。