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
的目的是什么?
I'm a bit confused regarding the difference between push_back
and emplace_back
.
void emplace_back(Type&& _Val);
void push_back(const Type& _Val);
void push_back(Type&& _Val);
As there is a push_back
overload taking a rvalue reference I don't quite see what the purpose of emplace_back
becomes?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
除了访客所说的之外:
MSCV10 提供的函数
void emplace_back(Type&& _Val)
是不合格且冗余的,因为正如您所指出的,它严格等同于push_back(Type& _Val) 。 &_Val)
。但
emplace_back
的真正 C++0x 形式确实很有用:void emplace_back(Args&&...)
;它不采用
value_type
,而是采用可变参数列表,因此这意味着您现在可以完美地转发参数并直接将对象构造到容器中,而无需使用临时对象。这很有用,因为无论 RVO 和移动语义给桌面带来了多少聪明,仍然存在
push_back
可能会进行不必要的复制(或移动)的复杂情况。例如,使用std::map
的传统insert()
函数,您必须创建一个临时文件,然后将其复制到std 中: :pair,然后将其复制到映射中:
那么为什么他们不在 MSVC 中实现正确版本的
emplace_back
呢?实际上,不久前它也困扰着我,所以我在 Visual C++ 博客。以下是 Microsoft Visual C++ 标准库实现的官方维护者 Stephan T Lavavej 的回答。这是一个可以理解的决定。每个尝试过使用预处理器可怕的技巧来模拟可变参数模板的人都知道这东西有多恶心。
In addition to what visitor said :
The function
void emplace_back(Type&& _Val)
provided by MSCV10 is non-conforming and redundant because as you noted it is strictly equivalent topush_back(Type&& _Val)
.But the real C++0x form of
emplace_back
is really useful:void emplace_back(Args&&...)
;Instead of taking a
value_type
, it takes a variadic list of arguments, so that means that you can now perfectly forward the arguments and construct directly an object into a container without a temporary at all.That's useful because no matter how much cleverness RVO and move semantics bring to the table, there are still complicated cases where a
push_back
is likely to make unnecessary copies (or move). For example, with the traditionalinsert()
function of astd::map
, you have to create a temporary, which will then be copied into astd::pair<Key, Value>
, which will then be copied into the map :So why didn't they implement the right version of
emplace_back
in MSVC? Actually, it bugged me too a while ago, so I asked the same question on the Visual C++ blog. Here is the answer from Stephan T Lavavej, the official maintainer of the Visual C++ standard library implementation at Microsoft.It's an understandable decision. Everyone who tried just once to emulate variadic template with preprocessor horrible tricks knows how disgusting this stuff gets.
emplace_back
不应采用vector::value_type
类型的参数,而应采用转发到附加项的构造函数的可变参数。可以传递一个
value_type
,它将被转发到复制构造函数。因为它转发参数,这意味着如果您没有右值,这仍然意味着容器将存储“复制的”副本,而不是移动的副本。
但上面的内容应该与
push_back
的作用相同。它可能更适合以下用例:emplace_back
shouldn't take an argument of typevector::value_type
, but instead variadic arguments that are forwarded to the constructor of the appended item.It is possible to pass a
value_type
which will be forwarded to the copy constructor.Because it forwards the arguments, this means that if you don't have rvalue, this still means that the container will store a "copied" copy, not a moved copy.
But the above should be identical to what
push_back
does. It is probably rather meant for use cases like:以下示例演示了
emplace_back
的优化。对于
emplace_back
,将调用构造函数A (int x_arg)
。对于
push_back
,首先调用A (int x_arg)
,然后调用move A (A &&rhs)
。当然,构造函数必须被标记为显式,但对于当前的示例,最好删除显式。
输出:
Optimization for
emplace_back
can be demonstrated in following example.For
emplace_back
, constructorA (int x_arg)
will be called.For
push_back
,A (int x_arg)
is called first andmove A (A &&rhs)
is called afterward.Of course, the constructor has to be marked as
explicit
, but for the current example, it is good to remove explicitness.output:
emplace_back
的具体用例:如果您需要创建一个临时对象,然后将其推送到容器中,请使用emplace_back
而不是push_back
。它将在容器内就地创建对象。注意:
push_back
将创建一个临时对象并移动它放入容器中。但是,用于
emplace_back
的就地构造会更有效比构造然后移动对象(通常涉及一些复制)更高效。
emplace_back
而不是push_back
,不会有太大问题。 (请参阅例外)Specific use case for
emplace_back
: If you need to create a temporary object which will then be pushed into a container, useemplace_back
instead ofpush_back
. It will create the object in-place within the container.Notes:
push_back
in the above case will create a temporary object and move itinto the container. However, in-place construction used for
emplace_back
would be moreperformant than constructing and then moving the object (which generally involves some copying).
emplace_back
instead ofpush_back
in all the cases without much issue. (See exceptions)列表的另一个示例:
One more example for lists:
这里显示了 Push_back 和 emplace_back 的一个很好的代码。
http://en.cppreference.com/w/cpp/container/vector/emplace_back
您可以在push_back上看到移动操作,而不是在emplace_back上看到移动操作。
A nice code for the push_back and emplace_back is shown here.
http://en.cppreference.com/w/cpp/container/vector/emplace_back
You can see the move operation on push_back and not on emplace_back.
当添加到向量时,符合
emplace_back
的实现会将参数转发给vector
使用
emplace_back
,如果将参数直接转发到vector
但注意这对于
std::map
可能很有用,因为一旦在映射中分配了一个条目,就不需要移动它或不再复制,这与vector
不同,这意味着您可以将std::map
有效地用于既不可复制也不可移动的映射类型。emplace_back
conforming implementation will forward arguments to thevector<Object>::value_type
constructor when added to the vector. I recall Visual Studio didn't support variadic templates, but with variadic templates will be supported in Visual Studio 2013 RC, so I guess a conforming signature will be added.With
emplace_back
, if you forward the arguments directly tovector<Object>::value_type
constructor, you don't need a type to be movable or copyable foremplace_back
function, strictly speaking. In thevector<NonCopyableNonMovableObject>
case, this is not useful, sincevector<Object>::value_type
needs a copyable or movable type to grow.But note that this could be useful for
std::map<Key, NonCopyableNonMovableObject>
, since once you allocate an entry in the map, it doesn't need to be moved or copied ever anymore, unlike withvector
, meaning that you can usestd::map
effectively with a mapped type that is neither copyable nor movable.emplace_back 函数是 std::vector 容器的一个方法。它构造一个新元素(例如,std::thread 对象)并将其直接附加到向量中。
例如:
The emplace_back function is a method of the std::vector container. It constructs and appends a new element (e.g., a std::thread object) directly to the vector.
For example: