C++:堆栈的 push() 与 emplace()

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26198350/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 11:33:06  来源:igfitidea点击:

C++: Stack's push() vs emplace()

c++stack

提问by Joshua Oliphant

Trying to understand the difference between using push()or emplace()for std::stack.

试图了解 usingpush()emplace()for之间的区别std::stack

I was thinking that if I create a std::stack<int>, then I'd use push()because integer is a primitive type and there is nothing for emplace()to construct.

我在想,如果我创建一个std::stack<int>,那么我会使用,push()因为 integer 是一种原始类型并且没有什么emplace()可构造的。

However, if I was creating std::stack<string>then I'd choose emplace()because std::stringis an object.

但是,如果我正在创建,std::stack<string>那么我会选择emplace()因为std::string是一个对象。

Is this correct usage?

这是正确的用法吗?

回答by Sam Varshavchik

To fully understand what emplace_back does, one must first understand variadic templates and rvalue references.

要完全理解 emplace_back 的作用,首先必须了解可变参数模板和右值引用。

This is a fairly advanced, and deep concept in modern C++. On a map, it would be labeled "there be dragons".

这是现代 C++ 中一个相当先进和深刻的概念。在地图上,它会被标记为“有龙”。

You say that you're new to C++ and trying to learn this stuff. This may not be the answer you might be looking for, but you should skip this detail for now, and come back later after you've wrapped your brain around variadic templates and rvalue references. Then it should all make sense.

你说你是 C++ 的新手并试图学习这些东西。这可能不是您可能正在寻找的答案,但您现在应该跳过这个细节,在您将大脑围绕可变参数模板和右值引用之后再回来。那么这一切都应该是有意义的。

But if you insist: for a container containing simple, elementary types like integers, there's little, if any difference. The difference comes when the container's type is some large, sophisticated class, with a complicated constructor, and/or copy-constructor.

但是,如果您坚持:对于包含简单、基本类型(如整数)的容器,几乎没有区别。当容器的类型是一些大的、复杂的类,具有复杂的构造函数和/或复制构造函数时,就会产生差异。

The end result of either push or emplace is exactly, 100%, the same. The container gets another element appended to it. The difference is where the element comes from:

push 或 emplace 的最终结果完全相同,100%。容器附加了另一个元素。不同之处在于元素来自哪里:

1) push takes an existing element, and appends a copy of it to the container. Simple, straightforward. push always takes exactly one argument, the element to copy to the container.

1) push 获取一个现有元素,并将其副本附加到容器中。简单,直接。push 总是只接受一个参数,即要复制到容器的元素。

2) emplace creates another instance of the class in the container, that's already appended to the container. The arguments to emplace are forwarded as arguments to the container's class's constructor. Emplace can have either one argument, more than one argument, or no argument at all, if the class has a default constructor.

2) emplace 在容器中创建该类的另一个实例,该实例已经附加到容器中。emplace 的参数作为参数转发给容器的类的构造函数。如果类具有默认构造函数,则 Emplace 可以有一个参数、多个参数或根本没有参数。

Note that when the class's constructor takes one argument and it is not marked as explicit, it's possible to abuse push and pass it a constructor argument, instead of an existing instance of the class. But let's pretend that this option does not exist, it often leads to horrible code performance, especially with non-trivial classes.

请注意,当类的构造函数接受一个参数且未标记为 时explicit,可能会滥用 push 并将构造函数参数传递给它,而不是该类的现有实例。但是让我们假设这个选项不存在,它通常会导致糟糕的代码性能,尤其是对于非平凡的类。

So: if you want to add a copy of an existing instance of the class to the container, use push. If you want to create a new instance of the class, from scratch, use emplace.

因此:如果要将类的现有实例的副本添加到容器中,请使用推送。如果要从头开始创建类的新实例,请使用 emplace。

回答by fredoverflow

If you have a vector<X>, then emplace_back(a, b, c)constructs the Xobject inside the vector.

如果您有vector<X>,则在向量内emplace_back(a, b, c)构造X对象。

By contrast, push_back(X(a, b, c))first creates a temporary, which is then moved into the vector.

相比之下,push_back(X(a, b, c))首先创建一个临时对象,然后将其移动到向量中。