20170323STL06_STL_SGI_vector

SGI vector:

  void push_back(const _Tp& __x) {
    if (_M_finish != _M_end_of_storage) {
      construct(_M_finish, __x);
      ++_M_finish;
    }
    else
      _M_insert_aux(end(), __x);//这个是可能会导致内存大小和地址发生改变的,这样外部指向他的指针也就失效了,这些指针需要更新
	//使用vector的时候一定要注意这点,内部重新分配空间的时候,外部指针会失效。
  }
  void swap(vector<_Tp, _Alloc>& __x) {//成员函数,接收的是一个模板类型一样的元素来互换
    __STD::swap(_M_start, __x._M_start);
    __STD::swap(_M_finish, __x._M_finish);
    __STD::swap(_M_end_of_storage, __x._M_end_of_storage);
  }
  iterator insert(iterator __position, const _Tp& __x) {
    size_type __n = __position - begin();
    if (_M_finish != _M_end_of_storage && __position == end()) {
      construct(_M_finish, __x);//空间足够且插入位置在最后,就直接构造这个(placement new)。
      ++_M_finish;
    }
    else
      _M_insert_aux(__position, __x);//在指定位置插入元素,也可能重新分配。
    return begin() + __n;
  }
template <class _Tp, class _Alloc>
void vector<_Tp, _Alloc>::_M_fill_insert(iterator __position, size_type __n, 
                                         const _Tp& __x)//指定位置插入一段一样的值。
{
  if (__n != 0) {
    if (size_type(_M_end_of_storage - _M_finish) >= __n) {
      _Tp __x_copy = __x;
      const size_type __elems_after = _M_finish - __position;//后面需要移动元素的数量
      iterator __old_finish = _M_finish;
      if (__elems_after > __n) {//如果需要往后移的元素个数比需要插入的多
        uninitialized_copy(_M_finish - __n, _M_finish, _M_finish);//先移动后面n个,有调用构造的(复制到为初始化空间需要构造)
        _M_finish += __n;
        copy_backward(__position, __old_finish - __n, __old_finish);
	//再移动前面部分,直接拷贝,不需构造(否则会导致构造函数和析构函数调用次数不一致,是undefined behavior。)
        fill(__position, __position + __n, __x_copy);//直接赋值,不需构造
      }
      else {//这个ifelse就是为了考虑需不需要构造才分开写的的,else里面有部分需要插入的元素会在已构造空间,有部分在未构造空间。
        uninitialized_fill_n(_M_finish, __n - __elems_after, __x_copy);//将未构造空间需要插入__x的部分全部构造成__x
        _M_finish += __n - __elems_after;
        uninitialized_copy(__position, __old_finish, _M_finish);//将需要移动的元素移动到_M_finish之后
        _M_finish += __elems_after;//更新最后位置
        fill(__position, __old_finish, __x_copy);//复制已构造空间部分的插入元素
      }
    }
    else {//重新分配空间,然后所有的空间操作都需要构造元素。
      const size_type __old_size = size();        
      const size_type __len = __old_size + max(__old_size, __n);//不一定是分配的两倍空间,插入元素过多,就分配的多
      iterator __new_start = _M_allocate(__len);
      iterator __new_finish = __new_start;
      __STL_TRY {
        __new_finish = uninitialized_copy(_M_start, __position, __new_start);
        __new_finish = uninitialized_fill_n(__new_finish, __n, __x);
        __new_finish
          = uninitialized_copy(__position, _M_finish, __new_finish);
      }
      __STL_UNWIND((destroy(__new_start,__new_finish), 
                    _M_deallocate(__new_start,__len)));
      destroy(_M_start, _M_finish);
      _M_deallocate(_M_start, _M_end_of_storage - _M_start);
      _M_start = __new_start;
      _M_finish = __new_finish;
      _M_end_of_storage = __new_start + __len;
    }
  }
}
  iterator erase(iterator __position) {//擦出指定位置的元素
    if (__position + 1 != end())
      copy(__position + 1, _M_finish, __position);//赋值后面的直接覆盖前面的,对象还是原来的,但是值改变了。
    --_M_finish;
    destroy(_M_finish);//析构最后一个(半闭半开)。他只是擦出值,如果里面存放的指针就可能发生泄漏。
    return __position;
  }


注意:如果vector里面装的指针,在查处的时候就会泄漏。
STL里面所有的容器都是浅拷贝,是值语义,他不会负责元素的生命周期,这样做是因为值语义是可以转化成对象语义的,对象语义没办法转换成值语义。
转换成对象语义:析构函数里面有delete就可以转换成对象语义,最常用的就是智能指针(就是将一个指针包装成一个类),还可以通过继承来做,但是用的很少。
STL里面的东西是不能改写,但是可以继承的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值