0
点赞
收藏
分享

微信扫一扫

C++Vector类详解

目录

1.Vector介绍

2.Vector的常见使用

   2.1 vector构造函数

   2.2 vector iterator使用

   2.3 vector空间增长问题

   2.4 vector增删改查

   2.5 vector迭代器失效问题

3.Vector深度剖析及模拟实现

   3.1 模拟实现(可跳过)

   3.2 不使用memcpy剖析


1.Vector介绍

2.Vector的常见使用

   2.1 vector构造函数

(constructor)构造函数声明接口说明
vector() 无参构造
vector (size_type n,const value_type&val=value_type())构造并初始化n个val

vector (const vector& x)

拷贝构造

vector (InputIterator fifirst, InputIterator last)

迭代器进行初始化构造

   2.2 vector iterator使用

iterator的使用接口说明
begin+end

获取第一个数据位置的 iterator/const_iterator , 获取最后一个数据的下一个位置的iterator/const_iterator

rbegin+rend

获取最后一个数据位置的 reverse_iterator ,获取第一个数据前一个位置的reverse_iterator

 简单使用例子:

void test1()
	{
		vector<int> V;
		V.push_back(1);
		V.push_back(2);
		V.push_back(3);
		V.push_back(4);
		vector<int>::iterator it = V.begin();
		while (it != V.end())
		{
			cout << *it << ' ';
			++it;
		}
		cout << endl;
		//反向迭代器
		vector<int>::reverse_iterator rit = V.rbegin();
		while (rit != V.rend())
		{
			cout << *rit << ' ';
			++rit;
		}
		cout << endl;
	}

 

   2.3 vector空间增长问题

容量空间接口说明
size获取数据个数
capacity获取容量大小
empty判断是否为空
resize改变vector的size
reserve改变vector的capacity

测试vector的默认扩容机制:

void TestVectorExpand()
	{
		size_t sz;
		vector<int> v;
		sz = v.capacity();
		cout << "making v grow:\n";
		for (int i = 0; i < 100; ++i)
		{
			v.push_back(i);
			if (sz != v.capacity())
			{
				sz = v.capacity();
				cout << "capacity changed: " << sz << '\n';
			}
		}
	}

vs下运行:

gcc下运行: 

	void test2()
	{
		vector<int> v;

		// set some initial content:
		for (int i = 1; i < 10; i++)
			v.push_back(i);

		v.resize(5);
		v.resize(8, 100);
		v.resize(12);
		cout << v.size() << endl;
		cout << "v contains:";
		for (size_t i = 0; i < v.size(); i++)
			cout << ' ' << v[i];
		cout << endl;
	}

 使用reserve提前设置好容量:

   2.4 vector增删改查

vector增删改查接口说明
push_back尾插
pop_back尾删
find查找(算法模块实现,不是vector成员接口)
insert在pos前插入val
erase删除pos位置数据
swap交换两个vector数据空间
operator[ ]像数组一样下标访问

 测试代码:

void test3()
	{
		vector<int> v{ 1,2,3,4 };//列表方式初始化,C++11新语法
		v.push_back(5);
		v.push_back(6);
		v.pop_back();
		for (size_t i = 0; i < v.size(); i++)
		{
			cout << v[i] << ' ';
		}
		cout << endl;
		vector<int>::iterator pos = find(v.begin(), v.end(), 3);
		if (pos != v.end())
		{
			v.insert(pos, 0);
		}
		pos = find(v.begin(), v.end(), 3);
		v.erase(pos);
		for (size_t i = 0; i < v.size(); i++)
		{
			cout << v[i] << ' ';
		}
		cout << endl;

	}

   2.5 vector迭代器失效问题

细心的朋友,可能已经发现我上面圈出来的重复find查找了一次,这是因为如果不再find给pos赋值,insert后不接受迭代器返回值继续erase会造成迭代器失效问题。 

对于vector可能会导致其迭代器失效的有效的操作有:

  • 会引起其底层空间改变的操作,都有可能是迭代器失效,比如:resize、reserve、insert、assign、push_back等。

        扩容后原来的pos已经失效,变为野指针。

        若不扩容insert后pos指向插入元素。

  • 指定位置元素的删除——erase

        erase删除pos位置元素后,pos位置之后的元素会往前搬移,没有导致底层空间的改变,理论上讲迭代器不应该会失效,但是: 如果pos刚好是最后一个元素,删完之后pos刚好是end的位置,而end位置是没有元素的,那么pos就失效了。

迭代器失效解决办法: 在使用前,对迭代器 重新赋值 即可

 

修改上面例子代码示例如下:

        vector<int>::iterator pos = find(v.begin(), v.end(), 3);
		if (pos != v.end())
		{
			pos=v.insert(pos, 0);
            //pos当前指向0
		}
        //删除3
		++pos;
		v.erase(pos);

3.Vector深度剖析及模拟实现

   3.1 模拟实现(可跳过)

        私有成员变量:与上图保持一致

		iterator _start;
		iterator _finish;
		iterator _end_of_storage;

        构造函数:

         拷贝构造函数:(现代写法)

swap:

         赋值运算符重载:(现代写法)

         析构函数:

         迭代器:

         size和capacity:

        reserve:(为什么不使用memcpy在后面将解)

         resize:

         operator[ ]:

        insert:

         erase:

         push_back,pop_back():(复用insert,erase)

   3.2 不使用memcpy剖析

        memcpy是浅拷贝

 假设一个vector<vector<int>>类型,实际内存分配:

 memcpy分配:(浅拷贝,释放2次空间,第二次为野指针造成内存泄漏)

 采取深拷贝(自己实现):

 


举报

相关推荐

0 条评论