STL篇:vector的用法注意事项以及模拟实现

本文详细阐述了C++中vector的用法注意事项,包括string与vector的区别、错误用法示例,以及vector的模拟实现,涉及内存管理、迭代器操作和浅拷贝问题。
摘要由CSDN通过智能技术生成

一、vector的用法注意事项
1、vector的用法与string相似,不再赘述。
2、vector与string区别:
string:要求最后有“\0”,更好地兼容c接口,它有很多它的专用接口(+=,比较大小等)
vector:没有“\0”,比较大小无意义
3、错误用法:有空间不一定能访问(reserve,resize之前必须初始化)

void test()
{
    vector<int> v1;
    v1.reserve(10);//虽然开了空间,但_finish指针依旧指向空,_size依旧为0
    for(size_t i = 0; i <= 10 ; i++)
    {
        v1[i] = i;
    }
}

4、二维数组vector<vector<int>>
5、迭代器区间:左闭右开[first,last)
失效的两种情况:
a.扩容或缩容
b.错位(并错过边界导致越界)
解决方案:
用it接收一下就好了(erase会返回删后位置指针iterator)
总结:
vector在erase和insert迭代器对象后不能再访问这个迭代器
我们认为它失效,访问结果是未定义
6、经典浅拷贝问题:
vector是深拷贝,但是vector空间上存的对象是string的数组,使用memcpy导致string对象的浅拷贝

二、vector的模拟实现以及测试


C++模板特殊处理后,内置类型也有构造函数

void test()
{
    int i = 0;
    int j = int();
    int k = int(1);
}

模拟实现

//vector.h
#pragma once

#include<assert.h>
//#include<string>
//#include<algorithm>//算法
#include<iostream>
using namespace std;

namespace star
{
	template<class T>
	class vector
	{
	public:

		typedef T* iterator;
		typedef const T* const_iterator;

		iterator begin()
		{
			return _start;
		}

		const_iterator begin() const
		{
			return _start;
		}

		iterator end()
		{
			return _finish;
		}

		const_iterator end() const
		{
			return _finish;
		}

		iterator reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t sz = size();//先保存size,否则后面_start的改变会影响size,从而影响_finish
				T* tmp = new T[n];
				if (_start)//判断是否有数据
				{
					//memcpy(tmp, _start, sizeof(T) * sz);//浅拷贝
					for (size_t i = 0; i < sz; i++)
					{
						tmp[i] = _start[i];
					}
					delete[] _start;
				}
				_start = tmp;
				_finish = _start + sz;
				_endofstorage = _start + n;
			}
			return _start;
		}

		iterator resize(size_t n, const T& val = T())//T()为匿名对象,需提供默认构造(C++有模板后对内置类型进行了升级,使其也有构造函数)
		{
			if (n < size())
			{
				_finish = _start + n;
			}
			else
			{
				reserve(n);
				while (_finish != _start + n)
				{
					*_finish = val;
					++_finish;
				}
			}
			return _start;
		}

		//构造函数:有效空间的地址不可能是零,空指针是无效地址,专门用作初始化
		vector()
			: _start(nullptr)
			, _finish(nullptr)
			, _endofstorage(nullptr)
		{}
		//拷贝构造(深拷贝)
		vector(const vector<T>& v)
			: _start(nullptr)
			, _finish(nullptr)
			, _endofstorage(nullptr)
		{
			_start = new T[v.capacity()];
			//memcpy(_start, v._start, sizeof(T)*v.size());//浅拷贝
			for (size_t i = 0; i < v.size(); i++)
			{
				_start[i] = v._start[i];
			}
			_finish = _start + v.size();
			_endofstorage = _start + v.capacity();
		}

		/*vector(const vector<T>& v)
			:_start(nullptr)
			, _finish(nullptr)
			, _endofstorage(nullptr)
		{
			reserve(v.capacity());
			for (auto e : v)
			{
				push_back(e);
			}
		}*/

		void swap(vector<T>& v)
		{
			std::swap(_start, v._start);
			std::swap(_finish, v._finish);
			std::swap(_endofstorage, v._endofstorage);
		}
		//赋值拷贝=
		vector<T>& operator=(vector<T> v)
		{
			swap(v);
			return *this;
		}

		vector(size_t n, const T& val = T())
		{
			resize(n, val);
		}

		vector(int n, const T& val = T())
		{
			resize(n, val);
		}
		//迭代器区间[first,last)初始化
		template<class InputIterator>
		vector(InputIterator first, InputIterator last)
		{
			while (first != last)
			{
				push_back(*first);
				first++;
			}
		}
		//析构函数
		~vector()
		{
			if (_start)
			{
				delete[] _start;
				_start = _finish = _endofstorage = nullptr;
			}
		}
		void push_back(const T& x)
		{
			if (_finish == _endofstorage)
			{
				size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
				reserve(newcapacity);
			}
			*_finish = x;
			++_finish;
			//insert(_finish, x);
		}

		void pop_back()
		{
			erase(--end());
		}

		iterator insert(iterator pos, const T& x)
		{
			assert(pos >= _start && pos <= _finish);
			if (_finish == _endofstorage)
			{
				size_t len = pos - _start;
				size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
				reserve(newcapacity);
				pos = _start + len;//解决迭代器失效问题:扩容后_start与_finish均改变,需而pos依旧(野指针),所以应返回接收新的pos
			}

			iterator _end = _finish - 1;
			while (_end >= pos)
			{
				*(_end + 1) = *_end;
				--_end;
			}
			*pos = x;
			_finish++;
			return pos;
		}

		iterator erase(iterator pos)
		{
			assert(pos >= _start && pos <= _finish);
			iterator it = pos + 1;
			while (it != _finish)
			{
				*(it - 1) = *it;
				it++;
			}
			--_finish;
			return pos;
		}

		T& operator[](size_t pos)
		{
			assert(pos <= size());
			return _start[pos];
		}

		const T& operator[](size_t pos) const
		{
			assert(pos <= size());
			return _start[pos];
		}

		size_t size() const
		{
			return _finish - _start;
		}

		size_t capacity() const
		{
			return _endofstorage - _start;
		}

	private:
		iterator _start;
		iterator _finish;
		iterator _endofstorage;
	};

	void print(const vector<int>& v)//只能打印const对象,需实现const迭代器
	{
		for (auto e : v)
		{
			cout << e << " ";
		}
		cout << endl;
	}
};

测试

//test.cpp
#include"vector.h"

using namespace star;

void test_vector1()
{
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	v1.push_back(5);

	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

	for (size_t i = 0; i < v1.size(); i++)
	{
		v1[i]++;
	}

	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

	print(v1);
}

void test_vector2()
{
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	v1.push_back(5);

	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

	v1.insert(v1.begin(), 100);

	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;


	vector<int>::iterator p = v1.begin() + 3;
	v1.insert(p, 300);

	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

	// 高危行为
	// *p += 10;

	// insert以后迭代器可能会失效(扩容),insert以后不要再使用这个形参迭代器了
	//因为pos是传值返回,形参改变不改变实参,若用引用,则会生成临时变量(具有常性),若用const引用,则pos = _start + len报错
}

void test_vector3()
{
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(2);
	v1.push_back(4);
	v1.push_back(5);
	v1.push_back(6);

	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

	// erase以后,迭代器失效了,不能访问
    // vs进行强制检查,访问会直接报错

	//解决方案
	auto it = v1.begin();
	while (it != v1.end())
	{
		if (*it % 2 == 0)
		{
			it = v1.erase(it);//接收迭代器返回值
		}
		else
		{
			++it;
		}
	}
}

void test_vector4()
{
	vector<int> v1;
	v1.resize(10, 0);

	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;


	vector<int> v2;
	v2.resize(10, 1);
	v2 = v1;
	for (auto e : v2)
	{
		cout << e << " ";
	}
	cout << endl;
}

void test_vector5()
{
	vector<string> v;
	v.push_back("111111111111111111");
	v.push_back("222222222222222222");
	v.push_back("333333333333333333");
	v.push_back("444444444444444444");
	v.push_back("555555555555555555");

	for (auto& e : v)
	{
		cout << e << " ";
	}
	cout << endl;

	vector<string> v1(v);
	for (auto& e : v1)
	{
		cout << e << " ";
	}
	cout << endl;
}

void test_vector6()
{
	vector<int> v(10u, 1);//u代表无符号整形
	vector<string> v1(10, "1111");

	vector<int> v2(10, 1);

	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl;


	vector<int> v3(v.begin(), v.end());
	for (auto e : v3)
	{
		cout << e << " ";
	}
	cout << endl;

	string str("hello world");
	vector<char> v4(str.begin(), str.end());
	for (auto e : v4)
	{
		cout << e << " ";
	}
	cout << endl;

	int a[] = { 16,2,77,29 };
	vector<int> v5(a, a + 4);
	for (auto e : v5)
	{
		cout << e << " ";
	}
	cout << endl;
}


 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值