4

看看这段代码:

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()在此过程中创建任何临时对象?

4

2 回答 2

6

不会有临时工。对于标准,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&)which 直接创建一个新对象Dummy(Dummy&)

在您的情况下 - 这两个复制构造函数之间没有区别。他们都会调用编译器隐式创建的普通复制构造函数。(1)所以你应该看到你的和(2)调用之间没有行为差异。

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

于 2014-11-03T15:50:54.753 回答
0

而不是采用 value_type emplace 采用可变参数列表,因此这意味着您现在可以完美地转发参数并将对象直接构造到容器中,而无需使用临时对象,这与可能涉及临时对象的推送相反。

以下是 emplace 的标准定义:-

将新元素压入栈顶。元素是就地构造的,即不执行复制或移动操作。使用与提供给函数的参数完全相同的参数调用元素的构造函数。

于 2014-11-03T15:44:47.683 回答