STL源码分析 # vector #

STL源码分析 # vector #


下面是一个使用vector的demo:

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    /*
    **  To create a vector which contain 10 elements and the value
    **  of each element is 1
    */
    vector<int> vec(10, 1);
    vector<int>::iterator iter = vec.begin();

    for (iter = vec.begin(); iter != vec.end(); iter++)
    {
        cout << *iter << endl;
    }

    return 0;
}



首先要知道class vector是 struct _Vector_base的衍生类.我们看看后者.

又包含一个基类struct _Vector_impl, 这里有三个指针,_M_start, _M_finish, _M_end_of_storage.

默认的初始化为0.

vector采用的数据结构非常简单,就是线性储存空间,它以两个迭代器_M_start, _M_finish分别指向配置得来的连续空间中目前已经使用的范围.并以迭代器_M_end_of_storage指向整块连续空间的尾部(包含备用空间)

_M_start 表示目前使用空间的头

_M_finish 表示目前使用空间的尾

_M_end_of_storage 表示目前可用空间的尾.




至于最后这里的不是很清楚,到现在都没找到如何在一大堆C++代码中快速的定位函数定义的位置.


我们测试一下这种内存构造布局.写个小demo:



/*
Programmer 	: EOF
Date			: 2015.03.31
file				: 4vector-test.cpp

Code description:
	This is a demo to show how the vector works.
*/
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main()
{
	int i = 0;
	vector<int> iv(2, 9);
	cout << "size" << iv.size() << endl;				// size = 2
	cout << "capacity = " << iv.capacity() << endl; 	// capacity = 2

	iv.push_back(1);
	cout << "size" << iv.size() << endl;				// size = 3
	cout << "capacity = " << iv.capacity() << endl; 	// capacity = 4

	iv.push_back(2);
	cout << "size" << iv.size() << endl;				// size = 4
	cout << "capacity = " << iv.capacity() << endl; 	// capacity = 4

	iv.push_back(3);
	cout << "size" << iv.size() << endl;				// size = 5
	cout << "capacity = " << iv.capacity() << endl; 	// capacity = 8

	iv.push_back(4);
	cout << "size" << iv.size() << endl;				// size = 6
	cout << "capacity = " << iv.capacity() << endl; 	// capacity = 8


	for (i = 0; i < iv.size(); i++)
	{
		cout << iv.at(i) << ' ';
	}
	cout << endl;

	iv.push_back(5);
	cout << "size" << iv.size() << endl;				// size = 
	cout << "capacity = " << iv.capacity() << endl; 	// capacity =	
	for (i = 0; i < iv.size(); i++)
	{
		cout << iv.at(i) << ' ';
	}
	cout << endl;

	iv.pop_back();
	iv.pop_back();
	cout << "size" << iv.size() << endl;				// size = 
	cout << "capacity = " << iv.capacity() << endl; 	// capacity =	

	iv.pop_back();
	cout << "size" << iv.size() << endl;				// size = 
	cout << "capacity = " << iv.capacity() << endl; 	// capacity =	

	vector<int>::iterator ivite = find(iv.begin(), iv.end(), 1);

	if (ivite != iv.end())
	{
		iv.erase(ivite);
	}

	cout << "size" << iv.size() << endl;				// size = 
	cout << "capacity = " << iv.capacity() << endl; 	// capacity =	
	for (i = 0; i < iv.size(); i++)
	{
		cout << iv.at(i) << ' ';
	}
	cout << endl;

	ivite = find(iv.begin(), iv.end(), 2);

	if( ivite != iv.end())
	{
		iv.insert(ivite, 3, 7);
	}

	cout << "size" << iv.size() << endl;				// size = 
	cout << "capacity = " << iv.capacity() << endl; 	// capacity =	
	for (i = 0; i < iv.size(); i++)
	{
		cout << iv.at(i) << ' ';
	}
	cout << endl;

	iv.clear();
	cout << "size" << iv.size() << endl;				// size = 
	cout << "capacity = " << iv.capacity() << endl; 	// capacity =	
	return 0;
}


size2
capacity = 2
size3
capacity = 4
size4
capacity = 4
size5
capacity = 8
size6
capacity = 8
9 9 1 2 3 4 
size7
capacity = 8
9 9 1 2 3 4 5 
size5
capacity = 8
size4
capacity = 8
size3
capacity = 8
9 9 2 
size6
capacity = 8
9 9 7 7 7 2 
size0
capacity = 8
[Finished in 0.6s]



vector用起来很像C语言的数组,但是这家伙又不是数组,而且比数组快更有效率.

而且还提供下标访问操作.




一下接口供用户访问查看当前vector占用的内存大小

值得注意的是max_size那里,好奇怪为嘛是-1...这里还不是很清楚.

这里应该是一个理论值,vector占满整个内存能装载几个_Tp类型的对象.



begin() end()返回迭代器,其实对于vector来说



我们注意到下标索引实质上是由指针运算实现的.返回引用

  reference operator[](size_type __n) { return *(begin() + __n); }
  const_reference operator[](size_type __n) const { return *(begin() + __n); }

和string一样!!下标索引是不安全的!!用at()函数

  reference at(size_type __n)
    { _M_range_check(__n); return (*this)[__n]; }
  const_reference at(size_type __n) const
    { _M_range_check(__n); return (*this)[__n]; }


vector的构造函数们~ 


  explicit vector(const allocator_type& __a = allocator_type()) //缺省参数,构造一个空的vector
    : _Base(__a) {}

  vector(size_type __n, const _Tp& __value,
         const allocator_type& __a = allocator_type())  //创建n个值为 __value的_Tp类型的vector
    : _Base(__n, __a)
    { _M_finish = uninitialized_fill_n(_M_start, __n, __value); }

  explicit vector(size_type __n)
    : _Base(__n, allocator_type())
    { _M_finish = uninitialized_fill_n(_M_start, __n, _Tp()); }

  vector(const vector<_Tp, _Alloc>& __x) //用别的vector初始化自己这个vector
    : _Base(__x.size(), __x.get_allocator())
    { _M_finish = uninitialized_copy(__x.begin(), __x.end(), _M_start); }

注意看析构函数,这里是调用destroy函数,从_M_start 到 _M_finish之间,而不是_M_start到_M_end_of_storage传递给destroy

  ~vector() { destroy(_M_start, _M_finish); }

我们常常会调用push_back把数据压入到当前vector的最后一个元素之后.

如果内存空间还富余的话(_M_finish 小于 _M_end_of_storage),利用构造函数在_M_finish处构造一个值为__x的vector元素.

如果内存空间不足了,就调用_M_insert_aux在尾部进行插入操作.push_back是没有返回值的!



很多函数都牵扯到_M_insert_aux,而这家伙的实现感觉又找不到,很奇怪...

有一个实现,但是第二个参数是bool在bvector.h里面


front() back()分别返回第一个元素的引用和最后元素的引用.




insert有各种重载,这里贴出一个

在迭代器指向的位置__position插入类型为_Tp的元素__x














erase会删除__first到__last之间的所有元素,而clear()则是调用erase删除所有元素.但是不缩减容量!!

只对_M_start, _M_end进行操作.







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值