小心emplace_back的传参限制,请显式传参!

起因介绍

今天在力扣刷题时,我发现了一个问题,当我使用emplace_back时会出现报错,但是使用push_back时不会。
在这里插入图片描述
在这里插入图片描述

在我之前的学习中学到的是两者语义相同,而emplace_back比push_back的效率更高,尽可能使用emplace_back。所以当我碰到这样的问题就开始出现了疑问,便开始在网上寻找原因。

原因分析

vector中的emplace_back和push_back都是用来在数组尾部添加元素的

emplace_back与push_back区别

push_back和emplace_back的底层实现逻辑不一样:
push_back在向数组尾部添加元素时,首先会创建这个元素,然后再将这个元素拷贝或者移动到容器中,如果是拷贝的话之后需要进行销毁;而 emplace_back() 在实现向数组尾部添加元素时,是直接在容器尾部创建这个元素,从而省去了拷贝或移动元素。这样可以看出是emplace_back效率更高

源码分析

emplace_back源码

template <class... _Valty>
    decltype(auto) emplace_back(_Valty&&... _Val) {
        // insert by perfectly forwarding into element at end, provide strong guarantee
        auto& _My_data   = _Mypair._Myval2;
        pointer& _Mylast = _My_data._Mylast;
        if (_Mylast != _My_data._Myend) {
            return _Emplace_back_with_unused_capacity(_STD forward<_Valty>(_Val)...);
        }

        _Ty& _Result = *_Emplace_reallocate(_Mylast, _STD forward<_Valty>(_Val)...);
#if _HAS_CXX17
        return _Result;
#else // ^^^ _HAS_CXX17 ^^^ // vvv !_HAS_CXX17 vvv
        (void) _Result;
#endif // _HAS_CXX17
    }

push_back源码

void push_back(const _Ty& _Val) { // insert element at end, provide strong guarantee
        emplace_back(_Val);
    }

    void push_back(_Ty&& _Val) { // insert by moving into element at end, provide strong guarantee
        emplace_back(_STD move(_Val));
    }

原来,push_back是调用了emplace_back,这应该是c++11的源码,因为emplace_back是c++11新增的,所以以前的push_back应该不是这样的。
阅读源码我们可以发现:push_back底层调用的就是emplace_back,所以理论上应该是不会发生这样的错误。
之后,我又继续寻找原因,之后在看了多篇技术文章之后终于知道了原因,那就是类型推导的原因,push_back在传入参数时是已知的数据类型,而emplace_back则是能接受任何类型的数据,而如果我们没有规定数据类型,则会陷入类似互相推导的死循环。

加上类型后

在这里插入图片描述
果然,给emplace_back加上类型限制后就可以通过了。

收获

虽然emplace_back在性能上优于push_back,一般情况下我们都使用emplace_back,但是记得在使用emplace_back时加上显式类型限制。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值