vector详解

文章目录

  • 目录
    • [1. vector的使用](#1. vector的使用)
      • [1.1 遍历](#1.1 遍历)
      • [1.2 插入](#1.2 插入)
      • [1.3 例题](#1.3 例题)
      • [1.4 排序](#1.4 排序)
      • [1.5 插入 + 删除 + 查找(算法库中的)](#1.5 插入 + 删除 + 查找(算法库中的))
    • [2. vector的模拟实现](#2. vector的模拟实现)
      • [2.1 尾插 + 下标+[ ]访问](#2.1 尾插 + 下标+[ ]访问)
      • [2.2 迭代器](#2.2 迭代器)
      • [2.3 尾删](#2.3 尾删)
      • [2.4 插入 + 删除](#2.4 插入 + 删除)
      • [2.5 构造 + 拷贝构造](#2.5 构造 + 拷贝构造)
      • [2.6 赋值运算符重载](#2.6 赋值运算符重载)
      • [2.7 用迭代器区间初始化](#2.7 用迭代器区间初始化)
      • [2.8 n个val初始化](#2.8 n个val初始化)
      • [2.9 initializer_list 的构造](#2.9 initializer_list 的构造)
      • [2.10 完整代码](#2.10 完整代码)

目录

  • vector的使用
  • vector的模拟实现

1. vector的使用

我们先来总的看一下它的一些接口:

  1. vector的定义
  2. vector iterator 的使用
  3. vector 空间增长问题

    注:
  • capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的。这个问题经常会考察,不要固化的认为,vector增容都是2倍,具体增长多少是根据具体的需求定义的。vs是PJ版本STL,g++是SGI版本STL。
  • reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题。
  • resize在开空间的同时还会进行初始化,影响size。
  1. vector 增删查改

接下来,我们通过一些场景来学习它的接口:

1.1 遍历

cpp 复制代码
#include <iostream>
using namespace std;

#include <vector>

void test_vector1()
{
	vector<double> v2;

	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);

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

	vector<int>::iterator it1 = v1.begin();
	while (it1 != v1.end())
	{
		cout << *it1 << " ";
		++it1;
	}
	cout << endl;

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

int main()
{
	test_vector1();

	return 0;
}

补充:

string 和 vector<char> 的区别:


1.2 插入

cpp 复制代码
#include <string>

void test_vector2()
{
	vector<string> v2;

	string s1("张三");
	v2.push_back(s1);
	v2.push_back(string("李四"));
	v2.push_back("王五");

	v2[1] += "来";

	//v2里的值赋值给e,因为是string类型,不加引用就要进行深拷贝
	for (const auto& e : v2)
	{
		cout << e << " ";
	}
	cout << endl;
}

int main()
{
	test_vector2();

	return 0;
}

1.3 例题

  • 只出现一次的数字
cpp 复制代码
class Solution
{
public:
    int singleNumber(vector<int>& nums)
    {
        int value = 0;
        for (auto e : nums)
        {
            value ^= e;
        }

        return value;
    }
};
  • 杨辉三角

cpp 复制代码
class Solution
{
public:
    vector<vector<int>> generate(int numRows)
    {
        vector<vector<int>> vv;
        vv.resize(numRows);
        for (size_t i = 0; i < numRows; ++i)
        {
            vv[i].resize(i + 1, 0);
            //每一行的第一个和最后一个初始化为1
            vv[i][0] = vv[i][vv[i].size() - 1] = 1;
        }

        for (size_t i = 0; i < vv.size(); ++i)
        {
            for (size_t j = 0; j < vv[i].size(); ++j)
            {
                if (0 == vv[i][j])
                {
                    vv[i][j] = vv[i - 1][j] + vv[i - 1][j - 1];
                }
            }
        }

        return vv;
    }
};

1.4 排序

cpp 复制代码
#include <algorithm>

void test_vector3()
{
	vector<int> v1;
	v1.push_back(10);
	v1.push_back(2);
	v1.push_back(30);
	v1.push_back(4);
	v1.push_back(44);
	v1.push_back(4);
	v1.push_back(40);
	v1.push_back(4);
	
	/*greater<int> gt;
	cout << gt(2, 3) << endl;
	cout << gt.operator()(2, 3) << endl;
	cout << gt(3, 2) << endl;*/
	
	//sort(v1.begin(), v1.end(), gt);
	//sort(v1.begin() + 1, v1.end() - 1);
	//sort(v1.begin(), v1.begin() + v1.size() / 2);

	//默认是升序
	//降序
	sort(v1.begin(), v1.end(), greater<int>());
	for (const auto& e : v1)
	{
		cout << e << " ";
	}
	cout << endl;
}

int main()
{
	test_vector3();

	return 0;
}

1.5 插入 + 删除 + 查找(算法库中的)

cpp 复制代码
#include <iostream>
#include <algorithm>
using namespace std;

#include <vector>

void test_vector4()
{
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

	v1.insert(v1.begin(), 0);
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;
	
	v1.erase(v1.begin());
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

	v1.insert(v1.begin() + 2, 20);
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

	int x;
	cin >> x;
	//没有x就不插入,有x的前面插入
	vector<int>::iterator pos = find(v1.begin(), v1.end(), x);
	if (pos != v1.end())
	{
		v1.insert(pos, 1000);
	}

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

int main()
{
	test_vector4();

	return 0;
}

2. vector的模拟实现

我们先自己写一下vector的成员变量:

cpp 复制代码
namespace bit
{
	template<class T>
	class vector
	{
	public:
	
	private:
		T* _a;
		size_t _size;
		size_t _capacity;
	};
}

接着,我们可以大致看一下SGI版本的vector的源码,看看它是怎么写的:

于是,我们就可以模仿它来进行模拟实现:

2.1 尾插 + 下标+[ ]访问

cpp 复制代码
#include <assert.h>
#include <iostream>
using namespace std;

namespace bit
{
	template<class T>
	class vector
	{
	public:
		typedef T* iterator;

		~vector()
		{
			if (_start)
			{
				delete[] _start;
				_start = _finish = _end_of_storage = nullptr;
			}
		}

		void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t oldsize = size();
				T* tmp = new T[n];
				
				if (_start)
				{
					memcpy(tmp, _start, sizeof(T) * size());//这样写是有问题的,下文有解释
					delete[] _start;
				}
				
				_start = tmp;
				_finish = _start + oldsize;
				_end_of_storage = _start + n;
			}
		}

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

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

		T& operator[](size_t i)
		{
			assert(i < size());

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

			return _start[i];
		}
		
		void push_back(const T& x)
		{
			if (_finish == _end_of_storage)
			{
				size_t newcapacity = 0 == capacity() ? 4 : capacity() * 2;
				reserve(newcapacity);
			}

			*_finish = x;
			++_finish;
		}

	private:
		/*T* _a;
		size_t _size;
		size_t _capacity;*/
	
		iterator _start = nullptr;
		iterator _finish = nullptr;
		iterator _end_of_storage = nullptr;
	};

	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(4);
		v1.push_back(4);

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

深层次的浅拷贝问题:

memcpy对任意类型拷贝都是浅拷贝


cpp 复制代码
void reserve(size_t n)
{
	if (n > capacity())
	{
		size_t oldsize = size();
		T* tmp = new T[n];

		if (_start)
		{
			//memcpy(tmp, _start, sizeof(T) * oldsize);//err
			for (size_t i = 0; i < oldsize; i++)
			{
				tmp[i] = _start[i];
			}
			
			delete[] _start;
		}

		_start = tmp;
		_finish = _start + oldsize;
		_end_of_storage = _start + n;
	}
}

void test_vector9()
{
	vector<string> v1;
	v1.push_back("111111111111111111");
	v1.push_back("111111111111111111");
	v1.push_back("111111111111111111");
	v1.push_back("111111111111111111");
	v1.push_back("111111111111111111");
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;
}

2.2 迭代器

cpp 复制代码
typedef T* iterator;
typedef const T* const_iterator;

const_iterator begin() const
{
	return _start;
}

const_iterator end() const
{
	return _finish;
}

iterator begin()
{
	return _start;
}

iterator end()
{
	return _finish;
}

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(4);
	v1.push_back(4);

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

	vector<int>::iterator it = v1.begin();
	while (it != v1.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
}

2.3 尾删

cpp 复制代码
void pop_back()
{
	assert(size() > 0);

	--_finish;
}

2.4 插入 + 删除

cpp 复制代码
iterator insert(iterator pos, const T& x)
{
	assert(pos >= _start);
	assert(pos <= _finish);

	if (_finish == _end_of_storage)
	{
		size_t len = pos - _start;

		size_t newcapacity = 0 == capacity() ? 4 : capacity() * 2;
		reserve(newcapacity);
	
		pos = _start + len;
	}

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

	return pos;
}

cpp 复制代码
void erase(iterator pos)
{
	assert(pos >= _start);
	assert(pos < _finish);

	iterator it = pos + 1;
	while (it != _finish)
	{
		*(it - 1) = *it;
		++it;
	}

	--_finish;
}
cpp 复制代码
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(), 0);
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

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

	v1.insert(v1.begin() + 2, 20);
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

	int x;
	cin >> x;
	//没有x就不插入,有x的前面插入
	vector<int>::iterator it = find(v1.begin(), v1.end(), x);
	if (it != v1.end())
	{
		// insert以后it这个实参会不会失效?
		it = v1.insert(it, 1000);
	
		//建议失效后的迭代器不要访问,除非赋值更新一下这个失效的迭代器
		cout << *it << endl;
	}

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

我们思考这样一个问题: erase之后,迭代器是否会失效呢?

失效。这里的失效和 insert 失效的原因不同,insert之后迭代器失效是因为扩容之后出现了野指针;而这里失效的原因是有些 erase 在实现时可能会缩容(很少会这样实现,但是也有),或者 erase 的是最后一个数据(虽然不是野指针,但是如果去访问也算是一种非法访问和越界)

库中给出的解决方案是给一个返回值,返回的是被删除数据的下一个数据的迭代器。

cpp 复制代码
void test_vector3()
{
	std::vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	v1.push_back(5);

	int x;
	cin >> x;
	std::vector<int>::iterator it = find(v1.begin(), v1.end(), x);
	if (it != v1.end())
	{
		//erase it以后,it是否失效呢?失效
		it = v1.erase(it);

		if (it != v1.end())
		{
			cout << *it << endl;
		}
	}
}

删除所有的偶数:

cpp 复制代码
void test_vector4()
{
	std::vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	v1.push_back(5);

	std::vector<int>::iterator it = v1.begin();
	while (it != v1.end())
	{
		if (0 == *it % 2)
		{
			//erase it以后,it是否失效呢?失效
			it = v1.erase(it);
		}
		else
		{
			++it;
		}
	}

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

注: 上面 erase 的代码在所有环境下都是可行的,如果不更新迭代器(不接收返回值),在Linux的g++下因为不是严格检查,所以能运行;但是在VS下因为严格检查就会报错。

2.5 构造 + 拷贝构造

cpp 复制代码
//强制编译器生成默认的
vector() = default;

//v2(v1)
vector(const vector<T>& v)
{
	reserve(v.capacity());
	for (auto e : v)
	{
		push_back(e);
	}
}

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

	vector<int> v2(v1);
	for (auto e : v2)
	{
		cout << e << " ";
	}
	cout << endl;
}

2.6 赋值运算符重载

cpp 复制代码
void swap(vector<T>& v)
{
	std::swap(_start, v._start);
	std::swap(_finish, v._finish);
	std::swap(_end_of_storage, v._end_of_storage);
}

//v1 = v3
vector<T>& operator=(vector<T> v)
{
	//this->swap(v);
	swap(v);
	return *this;
}

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

	vector<int> v3;
	v3.push_back(10);
	v3.push_back(20);
	v3.push_back(30);

	v1 = v3;

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

2.7 用迭代器区间初始化

cpp 复制代码
//类模板的成员函数
//函数模板 -- 目的支持任意容器的迭代器区间初始化
template<class InputIterator>
vector(InputIterator first, InputIterator last)
{
	while (first != last)
	{
		push_back(*first);
		++first;
	}
}

2.8 n个val初始化

cpp 复制代码
vector(size_t n, const T& val = T())
{
	reserve(n);
	for (size_t i = 0; i < n; i++)
	{
		push_back(val);
	}
}

//为了解决vector<int>时,传的两个参数都是int,因而去调用迭代器区间的构造
//因为迭代器区间的模板参数是两个相同的类型,比一个size_t,一个int的构造更符合
//所以我们要重载一个int,int的版本,这样有现成的函数就不会去调用由模板生成的函数了
vector(int n, const T& val = T())
{
	reserve(n);
	for (int i = 0; i < n; i++)
	{
		push_back(val);
	}
}

void test_vector7()
{
	//C++内置类型进行了升级,也有构造
	int i = 0;
	int j(1);
	int k = int();
	int x = int(2);

	vector<string> v1(10);
	vector<string> v2(10, "xxx");
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

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

	vector<int> v3(10u, 1);
	for (auto e : v3)
	{
		cout << e << " ";
	}
	cout << endl;

	vector<int> v4(10, 1);
	for (auto e : v4)
	{
		cout << e << " ";
	}
	cout << endl;
}

2.9 initializer_list 的构造

cpp 复制代码
vector(initializer_list<T> il)
{
	reserve(il.size());
	for (auto e : il)
	{
		push_back(e);
	}
}

class A
{
public:
	A(int a1 = 0)
		:_a1(a1)
		, _a2(0)
	{}

	A(int a1, int a2)
		:_a1(a1)
		, _a2(a2)
	{}
private:
	int _a1;
	int _a2;
};

void test_vector8()
{
	//单参数和多参数对象隐式类型转换
	//可以省略赋值符号
	//构造
	A aa1(1, 1);
	//通过构造实现的隐式类型转换 + 拷贝构造 -> 优化成构造
	A aa2 = { 2, 2 };
	A aa8{ 2, 2 };//建议不要这样写
	const A& aa9 = { 1, 1 };

	A aa3(1);
	A aa4 = 1;

	A aa5(1);
	A aa6 = { 1 };//建议不要这样写
	A aa7{ 1 };//建议不要这样写

	这是构造
	//std::vector<int> v1({ 1, 2, 3, 4, 5, 6 });
	这里的隐式类型转换,跟上面不一样,这里参数个数不固定
	//std::vector<int> v2 = { 10, 20, 30 };
	//for (auto e : v1)
	//{
	//	cout << e << " ";
	//}
	//cout << endl;

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

	//auto il1 = { 1, 2, 3, 4, 5, 6 };
	这个类里面定义了两个指针,一个指向开头,一个指向结尾的后一个
	//initializer_list<int> il2 = { 1, 2, 3 };
	//cout << typeid(il1).name() << endl;
	//cout << sizeof(il2) << endl;
	//
	这个类实现了迭代器,所以支持范围for
	还实现了size函数
	//for (auto e : il1)
	//{
	//	cout << e << " ";
	//}
	//cout << endl;


	vector<int> v1({ 1, 2, 3, 4, 5, 6 });
	vector<int> v2 = { 10, 20, 30 };
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

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

	vector<A> v3 = { 1, A(1), A(2, 2), A{1}, A{2,2}, {1}, {2,2} };
}

2.10 完整代码

cpp 复制代码
//vector.h

#include <assert.h>
#include <iostream>
using namespace std;

#include <algorithm>
#include <string>
#include <list>

namespace bit
{
	template<class T>
	class vector
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;

		const_iterator begin() const
		{
			return _start;
		}

		const_iterator end() const
		{
			return _finish;
		}

		iterator begin()
		{
			return _start;
		}

		iterator end()
		{
			return _finish;
		}

		//类模板的成员函数
		//函数模板 -- 目的支持任意容器的迭代器区间初始化
		template<class InputIterator>
		vector(InputIterator first, InputIterator last)
		{
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}

		vector(size_t n, const T& val = T())
		{
			reserve(n);
			for (size_t i = 0; i < n; i++)
			{
				push_back(val);
			}
		}

		//为了解决vector<int>时,传的两个参数都是int,因而去调用迭代器区间的构造
		//因为迭代器区间的模板参数是两个相同的类型,比一个size_t,一个int的构造更符合
		//所以我们要重载一个int,int的版本,这样有现成的函数就不会去调用由模板生成的函数了
		vector(int n, const T& val = T())
		{
			reserve(n);
			for (int i = 0; i < n; i++)
			{
				push_back(val);
			}
		}

		vector(initializer_list<T> il)
		{
			reserve(il.size());
			for (auto e : il)
			{
				push_back(e);
			}
		}

		//强制编译器生成默认的
		vector() = default;

		//v2(v1)
		vector(const vector<T>& v)
		{
			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(_end_of_storage, v._end_of_storage);
		}

		//v1 = v3
		vector<T>& operator=(vector<T> v)
		{
			//this->swap(v);
			swap(v);
			return *this;
		}

		~vector()
		{
			if (_start)
			{
				delete[] _start;
				_start = _finish = _end_of_storage = nullptr;
			}
		}

		void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t oldsize = size();
				T* tmp = new T[n];

				if (_start)
				{
					//memcpy(tmp, _start, sizeof(T) * oldsize);//err
					for (size_t i = 0; i < oldsize; i++)
					{
						tmp[i] = _start[i];
					}
					
					delete[] _start;
				}

				_start = tmp;
				_finish = _start + oldsize;
				_end_of_storage = _start + n;
			}
		}

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

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

		T& operator[](size_t i)
		{
			assert(i < size());

			return _start[i];
		}

		const T& operator[](size_t i) const
		{
			assert(i < size());

			return _start[i];
		}

		void push_back(const T& x)
		{
			/*if (_finish == _end_of_storage)
			{
				size_t newcapacity = 0 == capacity() ? 4 : capacity() * 2;
				reserve(newcapacity);
			}

			*_finish = x;
			++_finish;*/

			insert(end(), x);
		}

		void pop_back()
		{
			assert(size() > 0);

			--_finish;
		}

		iterator insert(iterator pos, const T& x)
		{
			assert(pos >= _start);
			assert(pos <= _finish);

			if (_finish == _end_of_storage)
			{
				size_t len = pos - _start;

				size_t newcapacity = 0 == capacity() ? 4 : capacity() * 2;
				reserve(newcapacity);

				pos = _start + len;
			}

			iterator end = _finish - 1;
			while (end >= pos)
			{
				*(end + 1) = *end;
				--end;
			}

			*pos = x;
			++_finish;

			return pos;
		}

		void erase(iterator pos)
		{
			assert(pos >= _start);
			assert(pos < _finish);

			iterator it = pos + 1;
			while (it != _finish)
			{
				*(it - 1) = *it;
				++it;
			}

			--_finish;
		}

	private:
		/*T* _a;
		size_t _size;
		size_t _capacity;*/

		iterator _start = nullptr;
		iterator _finish = nullptr;
		iterator _end_of_storage = nullptr;
	};

	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(4);
		v1.push_back(4);

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

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

		vector<int>::iterator it = v1.begin();
		while (it != v1.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;
	}

	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(), 0);
		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;

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

		v1.insert(v1.begin() + 2, 20);
		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;

		int x;
		cin >> x;
		//没有x就不插入,有x的前面插入
		vector<int>::iterator it = find(v1.begin(), v1.end(), x);
		if (it != v1.end())
		{
			// insert以后it这个实参会不会失效?
			it = v1.insert(it, 1000);

			//建议失效后的迭代器不要访问,除非赋值更新一下这个失效的迭代器
			cout << *it << endl;
		}

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

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

		int x;
		cin >> x;
		std::vector<int>::iterator it = find(v1.begin(), v1.end(), x);
		if (it != v1.end())
		{
			//erase it以后,it是否失效呢?失效
			it = v1.erase(it);

			if (it != v1.end())
			{
				cout << *it << endl;
			}
		}
	}

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

		std::vector<int>::iterator it = v1.begin();
		while (it != v1.end())
		{
			if (0 == *it % 2)
			{
				//erase it以后,it是否失效呢?失效
				it = v1.erase(it);
			}
			else
			{
				++it;
			}
		}

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

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

		vector<int> v2(v1);
		for (auto e : v2)
		{
			cout << e << " ";
		}
		cout << endl;

		vector<int> v3;
		v3.push_back(10);
		v3.push_back(20);
		v3.push_back(30);

		v1 = v3;

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

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

		vector<int> v2(v1.begin() + 1, v1.end());
		for (auto e : v2)
		{
			cout << e << " ";
		}
		cout << endl;

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

		list<int> lt;
		lt.push_back(100);
		lt.push_back(100);
		lt.push_back(100);
		vector<int> v4(lt.begin(), lt.end());
		for (auto e : v4)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	void test_vector7()
	{
		//C++内置类型进行了升级,也有构造
		int i = 0;
		int j(1);
		int k = int();
		int x = int(2);

		vector<string> v1(10);
		vector<string> v2(10, "xxx");
		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;

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

		vector<int> v3(10u, 1);
		for (auto e : v3)
		{
			cout << e << " ";
		}
		cout << endl;

		vector<int> v4(10, 1);
		for (auto e : v4)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	class A
	{
	public:
		A(int a1 = 0)
			:_a1(a1)
			, _a2(0)
		{}

		A(int a1, int a2)
			:_a1(a1)
			, _a2(a2)
		{}
	private:
		int _a1;
		int _a2;
	};

	void test_vector8()
	{
		//单参数和多参数对象隐式类型转换
		//可以省略赋值符号
		//构造
		A aa1(1, 1);
		//通过构造实现的隐式类型转换 + 拷贝构造 -> 优化成构造
		A aa2 = { 2, 2 };
		A aa8{ 2, 2 };//建议不要这样写
		const A& aa9 = { 1, 1 };

		A aa3(1);
		A aa4 = 1;

		A aa5(1);
		A aa6 = { 1 };//建议不要这样写
		A aa7{ 1 };//建议不要这样写

		这是构造
		//std::vector<int> v1({ 1, 2, 3, 4, 5, 6 });
		这里的隐式类型转换,跟上面不一样,这里参数个数不固定
		//std::vector<int> v2 = { 10, 20, 30 };
		//for (auto e : v1)
		//{
		//	cout << e << " ";
		//}
		//cout << endl;

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

		//auto il1 = { 1, 2, 3, 4, 5, 6 };
		这个类里面定义了两个指针,一个指向开头,一个指向结尾的后一个
		//initializer_list<int> il2 = { 1, 2, 3 };
		//cout << typeid(il1).name() << endl;
		//cout << sizeof(il2) << endl;
		//
		这个类实现了迭代器,所以支持范围for
		还实现了size函数
		//for (auto e : il1)
		//{
		//	cout << e << " ";
		//}
		//cout << endl;


		vector<int> v1({ 1, 2, 3, 4, 5, 6 });
		vector<int> v2 = { 10, 20, 30 };
		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;

		for (auto e : v2)
		{
			cout << e << " ";
		}
		cout << endl;
	
		vector<A> v3 = { 1, A(1), A(2, 2), A{1}, A{2,2}, {1}, {2,2} };
	}

	void test_vector9()
	{
		vector<string> v1;
		v1.push_back("111111111111111111");
		v1.push_back("111111111111111111");
		v1.push_back("111111111111111111");
		v1.push_back("111111111111111111");
		v1.push_back("111111111111111111");
		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;
	}
}
cpp 复制代码
//Test.cpp

#include "vector.h"

int main()
{
	bit::test_vector9();

	return 0;
}
相关推荐
每天减 1/5kg几秒前
创建者——建造者模式
开发语言·python·建造者模式
码道功成3 分钟前
快速创建基于Scala的flink开发项目
开发语言·flink·scala
New_Teen7 分钟前
C++小课堂——变量的声明,赋值和初始化
开发语言·c++·笔记·学习
练习&两年半17 分钟前
C语言:51单片机 程序设计基础
c语言·开发语言·单片机·51单片机
_Itachi__28 分钟前
LeetCode 热题100 21. 合并两个有序链表
算法·leetcode·链表
橘猫云计算机设计28 分钟前
基于微信小程序的疫情互助平台(源码+lw+部署文档+讲解),源码可白嫖!
java·大数据·开发语言·spring boot·微信小程序·小程序·汽车
努力努力再努力wz39 分钟前
【Linux实践系列】:用c语言实现一个shell外壳程序
linux·运维·服务器·c语言·c++·redis
Watink Cpper1 小时前
[MySQL初阶]MySQL(1)MySQL的理解、库的操作、表的操作
linux·运维·服务器·数据库·c++·后端·mysql
无世世1 小时前
【Java从入门到起飞】面向对象编程(基础)
java·开发语言
李白同学1 小时前
C++:类和对象(下篇)
开发语言·c++