您的位置:首页 > 其它

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里面的东西是不能改写,但是可以继承的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  stl sgi visual studio