emplace_back和push_back的异同

emplace_back和push_back在功能上是一致的,即在容器后方插入新的元素。那么相同逻辑的功能问什么要实现两边,以及为什么会有人推荐使用emplace_back代替push_back呢!

异同

相同点:

        1. 支持传入右值 (push_back是c++11后才支持的)

不同点:

        push_back: 

                a. 一定会发生拷贝构造

                b. 不支持原地构造

                c. 支持一个构造函数(此时其实也是发生了隐式构造)

        emplace_back:

                a. 不一定会发生拷贝构造

                b. 支持原地构造

                c. 支持多个构造函数

push_back

假设有一个std::vector<T> array,则array调用push_back时传入的变量只能是T类型的(当该类型构造函数只有一个参数时可以传入这个参数,发生隐式构造,实质上传入push_back的还是T类型的变量)。

细想一下这样的规则会发生什么,如果我们有一个如下类型的vector

class EXAMPLE
{
public:
    EXAMPLE() = delete;
    EXAMPLE(int a, int b)
        : a_(a)
        , b_(b)
    {}

private:
    int a_;
    int b_;
}

int main()
{
    std::vector<EXAMPLE> array;
    array.push_back(1, 2); // 编译出错,push_back不支持原地构造
    array.push_back({ 1, 2 }); // 编译成功
    return 0;
}

上面代码中执行array.psuh_back({ a, b })首先会执行EXAMPLE的构造函数构造一个临时的EXAMPLE对象,接下来会调用拷贝构造函数将临时对象放到vector中。想一下若该类很大,执行拷贝构造效率很低,并且push_back被调用很多次,此时会造成很多性能的浪费。

emplace_back

若使用emplace_back便可以避免push_back带来的性能浪费。

int main()
{
    std::vector<EXAMPLE> array;
    array.emplace_back(1, 2); // 编译成功
    array.emplace_back({ 1, 2 }); // 编译出错
    array.emplace_back(EXAMPLE(1, 2)); // 编译成功
    return 0;
}

array.emplace_back(1, 2)会执行原地构造,在emplace_back内部构造,不会发生拷贝构造。array.emplace_back(EXAMPLE(1, 2))会先构造一个临时的对象,再执行拷贝构造放入vector中。

总结

虽然在性能方面emplace_back优于push_back,但emplace_back也有一些缺点:

        1. emplace_back一般发生错误都会在比较深的位置,而push_back则更容易定位问题

        2. push_back是函数,可以支持隐式转换,而emplace_back本质上是模板,不支持隐式转换

  • 20
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值