20170323STL06_STL_SGI_vector
2017-03-22 22:32
393 查看
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里面的东西是不能改写,但是可以继承的。
相关文章推荐
- 20170323STL06_STL_SGI_vector
- 20170323STL06_STL_SGI_vector
- 20170323STL06_STL_SGI_vector
- 20170323STL06_STL_SGI_vector
- 20170323STL06_STL_SGI_vector
- 20170323STL06_STL_SGI_vector
- 20170323STL06_STL_SGI_vector
- 20170323STL06_STL_SGI_vector
- C++ Standard Stl -- SGI STL源码学习笔记(06) stl_vector 与 一些问题的细化 2 push_back函数剖析
- SGI STL的序列式容器之vector浅析
- C++ Standard Stl -- SGI STL源码学习笔记(05) stl_vector 与 一些问题的细化 1
- SGI STL代码剖析之Vector(二)
- C++ Standard Stl -- SGI STL源码学习笔记(07) stl_vector 与 一些问题的细化 3 resize函数剖析
- SGI STL原代码分析之Vector(一)。
- SGI源码注释之stl_vector.h初窥
- SGI STL 和 VS下STL的vector不同内存增长策略
- SGI STL源码之vector
- vector (仿sgi stl)
- SGI STL 学习笔记二 vector
- STL之vector