关于push_back和emplace_back之间的区别,我有点困惑。
void emplace_back(Type&& _Val);
void push_back(const Type& _Val);
void push_back(Type&& _Val);
由于有一个push_back重载取右值引用,我不太清楚emplace_back的目的是什么?
关于push_back和emplace_back之间的区别,我有点困惑。
void emplace_back(Type&& _Val);
void push_back(const Type& _Val);
void push_back(Type&& _Val);
由于有一个push_back重载取右值引用,我不太清楚emplace_back的目的是什么?
当前回答
emplace_back的优化可以在下一个示例中演示。
对于emplace_back,将调用构造函数A (int x_arg)。和 首先调用push_back A (int x_arg),然后调用move A (A &&rhs)。
当然,构造函数必须被标记为显式的,但对于当前的示例来说,删除显式是很好的。
#include <iostream>
#include <vector>
class A
{
public:
A (int x_arg) : x (x_arg) { std::cout << "A (x_arg)\n"; }
A () { x = 0; std::cout << "A ()\n"; }
A (const A &rhs) noexcept { x = rhs.x; std::cout << "A (A &)\n"; }
A (A &&rhs) noexcept { x = rhs.x; std::cout << "A (A &&)\n"; }
private:
int x;
};
int main ()
{
{
std::vector<A> a;
std::cout << "call emplace_back:\n";
a.emplace_back (0);
}
{
std::vector<A> a;
std::cout << "call push_back:\n";
a.push_back (1);
}
return 0;
}
输出:
call emplace_back:
A (x_arg)
call push_back:
A (x_arg)
A (A &&)
其他回答
这里显示了push_back和emplace_back的代码。
http://en.cppreference.com/w/cpp/container/vector/emplace_back
您可以在push_back上看到移动操作,而在emplace_back上看不到。
emplace_back的特定用例:如果您需要创建一个临时对象,然后将其推入容器,请使用emplace_back而不是push_back。它将在容器内就地创建对象。
注:
上面例子中的Push_back将创建一个临时对象并移动它 放进容器里。然而,用于emplace_back的in-place结构将更多 性能比构造然后移动对象(通常涉及一些复制)。 一般来说,在所有情况下都可以使用emplace_back而不是push_back,没有太多问题。(见异常)
还有一个关于列表的例子:
// constructs the elements in place.
emplace_back("element");
// creates a new object and then copies (or moves) that object.
push_back(ExplicitDataType{"element"});
emplace_back的优化可以在下一个示例中演示。
对于emplace_back,将调用构造函数A (int x_arg)。和 首先调用push_back A (int x_arg),然后调用move A (A &&rhs)。
当然,构造函数必须被标记为显式的,但对于当前的示例来说,删除显式是很好的。
#include <iostream>
#include <vector>
class A
{
public:
A (int x_arg) : x (x_arg) { std::cout << "A (x_arg)\n"; }
A () { x = 0; std::cout << "A ()\n"; }
A (const A &rhs) noexcept { x = rhs.x; std::cout << "A (A &)\n"; }
A (A &&rhs) noexcept { x = rhs.x; std::cout << "A (A &&)\n"; }
private:
int x;
};
int main ()
{
{
std::vector<A> a;
std::cout << "call emplace_back:\n";
a.emplace_back (0);
}
{
std::vector<A> a;
std::cout << "call push_back:\n";
a.push_back (1);
}
return 0;
}
输出:
call emplace_back:
A (x_arg)
call push_back:
A (x_arg)
A (A &&)
遵从emplace_back的实现在添加到vector时将参数转发给vector<Object>::value_typeconstructor。我记得Visual Studio不支持可变参数模板,但是在Visual Studio 2013 RC中支持可变参数模板,所以我猜一个符合标准的签名将被添加。
使用emplace_back,如果直接将参数转发给vector<Object>::value_type构造函数,严格地说,emplace_back函数不需要一个可移动或可复制的类型。在vector<NonCopyableNonMovableObject>的情况下,这是没有用的,因为vector<Object>::value_type需要一个可复制或可移动的类型来增长。
但请注意,这对于std::map<Key, NonCopyableNonMovableObject>可能很有用,因为一旦你在映射中分配了一个条目,它就不需要再移动或复制了,不像vector,这意味着你可以有效地将std::map用于既不可复制也不可移动的映射类型。