在这种情况下,std :: stack :: push()和std :: stack :: emplace()之间有区别吗?

时间:2014-11-03 15:28:55

标签: c++ c++11 emplace

看看这段代码:

struct Dummy
{
    int bla;
    int blabla;
    char character;

    Dummy (int b, int bb, char c)
        : bla(b), blabla(bb), character(c)
    {}
};

std::stack<Dummy> s;
Dummy dummy;
s.push(dummy);   // (1)
s.emplace(dummy);   // (2)

我看不出(1)(2)之间的区别。我知道emplace()在为要添加的对象的构造函数提供参数时非常有用,例如:

s.emplace(1, 2, 'c');

但我不知道在我描述的情况下有什么区别,因为push()emplace()都应该引用本地dummy对象并创建一个新对象复制ctor或类似的东西。 push()是否在流程中创建了任何临时对象?

2 个答案:

答案 0 :(得分:5)

没有临时的人。对于标准,push看起来像:

void push(const value_type& x) { c.push_back(x); }
void push(value_type&& x) { c.push_back(std::move(x)); }

emplace看起来像:

template <class... Args>
void emplace(Args&&... args) { 
    c.emplace_back(std::forward<Args>(args)...);
}

c是底层容器,默认为deque<T>。因此,在前一种情况下,当您调用push时,您正在调用push(const Dummy&),它将通过Dummy(const Dummy&)创建一个新对象。在后一种情况下,您调用emplace_back(Dummy&),通过Dummy(Dummy&)直接创建新对象。

在您的情况下 - 这两个副本构造函数之间没有区别。它们都会调用由编译器隐式创建的普通复制构造函数。因此,您应该看到(1)(2)来电之间没有任何行为差异。

如果一个或另一个构造函数不存在(在这种情况下,一个或另一个不能编译),或者如果它们做了不同的事情,那么只会有区别。

答案 1 :(得分:0)

取代获取value_type emplace取代变量的参数列表,这意味着你现在可以完美地转发参数并直接将一个对象构造成一个容器,而不是临时的,这可能涉及临时工具。

以下是emplace的标准定义: -

将新元素推送到堆栈顶部。该元素就地构造,即不执行复制或移动操作。调用元素的构造函数时使用与提供给函数完全相同的参数。