C ++:堆栈的 push() 与 emplace() [重复]
Posted
技术标签:
【中文标题】C ++:堆栈的 push() 与 emplace() [重复]【英文标题】:C++: Stack's push() vs emplace() [duplicate] 【发布时间】:2014-11-29 15:46:33 【问题描述】:试图了解使用push()
或emplace()
与std::stack
之间的区别。
我在想,如果我创建一个std::stack<int>
,那么我会使用push()
,因为整数是一个原始类型,emplace()
没有什么可以构造的。
但是,如果我正在创建 std::stack<string>
,那么我会选择 emplace()
,因为 std::string
是一个对象。
这是正确的用法吗?
【问题讨论】:
我已经读过 push_back vs emplace_back,或者至少尝试过,但我想知道是否有人对像我这样对 c++ 有点陌生的人有更简单的答案。 不是重复的。那个人实际上要问的是一个 MSVC10 错误。尽管这个问题可能已经被问过,但在其他地方并没有被问到。 为什么大家都在谈论这个 emplace_back() 的事情?我对 C++11 emplace() 方法以及使用 push() 的意义很感兴趣。 cplusplus.com/reference/stack/stack/emplace 【参考方案1】:要完全理解 emplace_back 的作用,首先必须了解可变参数模板和右值引用。
这是现代 C++ 中一个相当先进和深刻的概念。在地图上,它会被标记为“有龙”。
你说你是 C++ 的新手,并试图学习这些东西。这可能不是您正在寻找的答案,但您现在应该跳过这个细节,等您将大脑包裹在可变参数模板和右值引用上之后再回来。那么这一切都应该是有意义的。
但是,如果您坚持:对于包含简单的基本类型(如整数)的容器,几乎没有区别,如果有的话。当容器的类型是一些大型的、复杂的类,具有复杂的构造函数和/或复制构造函数时,差异就出现了。
push 或 emplace 的最终结果完全相同,100% 相同。容器获取附加到它的另一个元素。不同之处在于元素的来源:
1) push 获取一个现有元素,并将其副本附加到容器中。简单,直接。 push 总是只接受一个参数,即要复制到容器的元素。
2) emplace 在容器中创建该类的另一个实例,该实例已经附加到容器中。 emplace 的参数作为参数转发给容器类的构造函数。如果类具有默认构造函数,Emplace 可以有一个参数、多个参数或根本没有参数。
请注意,当类的构造函数采用一个参数并且未标记为explicit
时,可能会滥用 push 并将其传递给构造函数参数,而不是类的现有实例。但是让我们假设这个选项不存在,它通常会导致糟糕的代码性能,尤其是对于非平凡的类。
所以:如果您想将现有类实例的副本添加到容器中,请使用 push。如果您想从头开始创建该类的新实例,请使用 emplace。
【讨论】:
我想我明白什么时候我会使用 emplacement 而不是 push。我肯定会查找有关可变参数模板和右值引用的信息。 即使我要添加的对象已经存在,总是使用emplace
会有什么缺点吗?
@antred - push_back() 允许统一的初始化语法。 emplace_back(),因为它是一个模板函数,所以没有。【参考方案2】:
如果您有vector<X>
,则emplace_back(a, b, c)
在向量内构造X
对象。
相比之下,push_back(X(a, b, c))
首先创建一个临时对象,然后将其移动到向量中。
【讨论】:
那么,emplace_back(X(a,b,c))
呢?
这将创建临时 X(a,b,c),并尝试在将临时作为参数的向量内构造 X,这应该使用移动构造函数。一般来说,如果您想知道 emplace 会发生什么,请问自己“如果我将 emplace_back 替换为对象名称会发生什么”?它基本上就是这样做的——除了它使用的内存正是向量想要的位置,因此避免了 push_back 需要做的额外移动/复制步骤。以上是关于C ++:堆栈的 push() 与 emplace() [重复]的主要内容,如果未能解决你的问题,请参考以下文章
为啥我会使用 push_back 而不是 emplace_back?
c_cpp emplace_back()和push_back()