天天看點

insert與copy的插入比較

舉例代碼:

将一段資料複制到vector的首部

int data[5] = {0,1,2,3,4};
vector<int> vInt;
vInt.push_back(10);
vInt.insert(vInt.begin(),data,data+5);

vInt.clear();
vInt.push_back(10);
copy(data, data+5, inserter(vInt,vInt.begin()));      

檢視copy方法的實作:

template<class InputIt, class OutputIt>
OutputIt copy(InputIt first, InputIt last, 
              OutputIt d_first)
{
    while (first != last) {
        *d_first++ = *first++;
    }
    return      

copy的第三個參數inserter是這樣的:

template< class Container
std::insert_iterator<Container> inserter( Container& c, typename Container::iterator i )
{
    return std::insert_iterator<Container>(c, i);
}      

insert_iterator的實作是這樣的:

_LIBCPP_INLINE_VISIBILITY insert_iterator(_Container& __x, typename _Container::iterator __i)
        : container(_VSTD::addressof(__x)), iter(__i) {}      

對,其實就是構造了一個容器。

insert_iterator是一個類,不同的容器以模闆泛型程式設計的方式被類實作。copy每調用一次​​

​inserter(d_first)​

​​即申請記憶體建立對象,随即進行資料複制​

​(*d_first++ = *first++)​

​。

insert方法中相關的底層函數調用

vector::__move_range ==> std::move_backward ==> std::move

move_range:

template <class _Tp, class _Allocator>
void
vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointer __to)
{
    pointer __old_last = this->__end_;
    difference_type __n = __old_last - __to;
    for (pointer __i = __from_s + __n; __i < __from_e; ++__i, ++this->__end_)
        __alloc_traits::construct(this->__alloc(),
                                  _VSTD::__to_raw_pointer(this->__end_),
                                  _VSTD::move(*__i));
    _VSTD::move_backward(__from_s, __from_s + __n, __old_last);
}      

在循環中申請了一段區間記憶體,然後一次性move_backward.

move_backward

template< class BidirIt1, class BidirIt2 >
BidirIt2 move_backward(BidirIt1 first,
                                    BidirIt1 last,
                                    BidirIt2 d_last)
{
    while (first != last) {
        *(--d_last) = std::move(*(--last));
    }
    return      
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
const _Tp&
move(const _Tp& __t)
{
    return