C++_泛型编程与标准库(七)

C++_泛型编程与标准库(七)

参考:《侯捷泛化编程与标准库》、VC2019

图中标红部分为自己的笔记理解

1、深度探索vector

  1. 笔者觉得在最新的VC2019下不是二倍增长,虽然是几何增长,但是增加的是之前的1/2;不是完全二倍增长

  2. 在VC2019的32位程序下,vector类型大小是16位的,其中包含了3个4位的功能同start,finish,end_of_storage的指针,还有4位是继承基类容器(_Container_base12)里的指针而来的四个字节;

    struct _Container_base12 {
    _Container_proxy* _Myproxy = nullptr;
    }
    template <class _Val_types>
    class _Vector_val : public _Container_base {
    public:
        pointer _Myfirst; // pointer to beginning of array
        pointer _Mylast; // pointer to current end of sequence
        pointer _Myend; // pointer to end of array
    };
    

VC2019push_back()调用的是emplace_back(),而emplace_back()的处理方式与侯捷老师说的gnu2.9的类似

_CONSTEXPR20_CONTAINER void push_back(const _Ty& _Val) { // insert element at end, provide strong guarantee
        emplace_back(_Val);//push_back()调用emplace_back()
}
template <class... _Valty>
    _CONSTEXPR20_CONTAINER 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
    }

2、GNU2.9的vector容器增长与VC2019的区别

  1. GNU2.9的增长

    大量调用构造与析构

  2. VC2019的增长,只增长之前的1/2

 template <class... _Valty>
    _CONSTEXPR20_CONTAINER pointer _Emplace_reallocate(const pointer _Whereptr, _Valty&&... _Val) {//重新分配内存
        // reallocate and insert by perfectly forwarding _Val at _Whereptr
        _Alty& _Al        = _Getal();
        auto& _My_data    = _Mypair._Myval2;//mypair是vector类中的_Compressed_pair的类型
        pointer& _Myfirst = _My_data._Myfirst;//获取数据头指针
        pointer& _Mylast  = _My_data._Mylast;//获取数据最新尾部指针

        _STL_INTERNAL_CHECK(_Mylast == _My_data._Myend); // check that we have no unused capacity
														//检查是否有没有用的空间
        const auto _Whereoff = static_cast<size_type>(_Whereptr - _Myfirst);
        const auto _Oldsize  = static_cast<size_type>(_Mylast - _Myfirst);//获取旧空间大小

        if (_Oldsize == max_size()) {
            _Xlength();
        }

        const size_type _Newsize     = _Oldsize + 1;//新空间等于旧空间+1
        const size_type _Newcapacity = _Calculate_growth(_Newsize);//新容量等于_Oldcapacity + _Oldcapacity / 2;或者_Newsize

        const pointer _Newvec           = _Al.allocate(_Newcapacity);//分配新内存,返回新空间地址(指针)
        const pointer _Constructed_last = _Newvec + _Whereoff + 1;
        pointer _Constructed_first      = _Constructed_last;//应当存放新data的空间

        _TRY_BEGIN//尝试构造
        _Alty_traits::construct(_Al, _Unfancy(_Newvec + _Whereoff), _STD forward<_Valty>(_Val)...);
        _Constructed_first = _Newvec + _Whereoff;

        if (_Whereptr == _Mylast) { // at back, provide strong guarantee
            _Umove_if_noexcept(_Myfirst, _Mylast, _Newvec);
        } else { // provide basic guarantee
            _Umove(_Myfirst, _Whereptr, _Newvec);
            _Constructed_first = _Newvec;
            _Umove(_Whereptr, _Mylast, _Newvec + _Whereoff + 1);
        }
        _CATCH_ALL//异常则释放空间
        _Destroy(_Constructed_first, _Constructed_last);
        _Al.deallocate(_Newvec, _Newcapacity);
        _RERAISE;
        _CATCH_END

        _Change_array(_Newvec, _Newsize, _Newcapacity);
        return _Newvec + _Whereoff;//返回新data数据指针
}
 _CONSTEXPR20_CONTAINER size_type _Calculate_growth(const size_type _Newsize) const {
     // given _Oldcapacity and _Newsize, calculate geometric growth
     const size_type _Oldcapacity = capacity();
     const auto _Max              = max_size();

     if (_Oldcapacity > _Max - _Oldcapacity / 2) {
         return _Max; // geometric growth would overflow
     }

     const size_type _Geometric = _Oldcapacity + _Oldcapacity / 2;//在此处增加了之前1/2的空间

     if (_Geometric < _Newsize) {
         return _Newsize; // geometric growth would be insufficient
     }

     return _Geometric; // geometric growth is sufficient
 }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值