深入剖析vector的底层实现原理

1:vector各函数接口

2:vector当中的成员变量介绍

3:默认成员函数

3.1:构造函数1

3.2:构造函数2

3.3:构造函数3

3.4:拷贝构造函数

3.4.1:第一种写法

3.4.2:第二种写法

3.5:赋值运算符重载

3.6:析构函数

4:迭代器相关函数

4.1:begin与end

5:容量和大小相关函数

5.1:size与capacity

5.2:reserve

5.2.1:拷贝数据问题

5.3:resize

5.4:empty

6:修改容器内容相关函数

6.1:push_back

6.2:pop_back

6.3:insert

6.4:erase

6.5:swap

7:访问容器相关函数

8:相关测试

8.1:测试默认成员函数

8.2:测试迭代器相关函数

8.3:测试容量与大小相关函数

8.4:测试尾插与尾删

8.5:测试insert与erase与Swap

9:总代码

9.1:vector.h

9.2:Test.cpp


1:vector各函数接口

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

namespace MyVector 
{
	template <class T>
	class vector
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;
		//默认成员函数
		vector();//构造函数
		vector(size_t n, const T& val);//构造函数
		template <class InputIterator>
		vector(InputIterator first, InputIterator last);//迭代器区间构造
		vector (const vector<T> v);//拷贝构造函数
		vector<T>& operator=(const vector<T>& x);//赋值运算符重载
		~vector();//析构函数

		//迭代器相关函数
		iterator begin();
		iterator end();
		const_iterator begin() const;
		const_iterator end() const;

		//容量相关函数
		size_t size() const;
		size_t capacity() const;
		void reserve(size_t n);
		void resize(size_t n, const T& val = T());
		bool empty() const;
		
		//元素访问相关函数
		T& operator[](size_t n);
		const T& operator[](size_t n) const;

		//修改容器相关函数
		void push_back(const T& val);
		void pop_back();
		iterator insert(iterator position, const T& val);
		iterator erase(iterator position);
		void swap(vector <T>& v1);
	private:
		iterator start;//指向数组起始位置
		iterator finish;//指向数组最后一个元素的下一个位置
		iterator end_of_storage;//指向数组的最后位置
	};
}
  • PS:为了防止和标准库中的进行冲突,所以使用命名空间将其包裹起来.

2:vector当中的成员变量介绍

  • _start:指向容器的头.
  • _end:指向有效数据的尾.
  • _endofstorage:指向整个容器的尾部.

3:默认成员函数

3.1:构造函数1

cpp 复制代码
		//默认成员函数
		vector()
			:_start(nullptr)
			,_finish(nullptr)
			,_end_of_storage(nullptr)
		{

		}

vector首先支持一个无参的构造函数,对于这个无参的构造函数,直接将构造对象的三个成员变量都设置为空指针即可.

3.2:构造函数2

cpp 复制代码
		vector(size_t n, const T& val)
		{
			_start = new T[n];
			_finish = _start + n;
			_end_of_storage = _finish;
			for (size_t i = 0; i < n; i++)
			{
				_start[i] = val;
			}
		}

对于使用n个值去构造该容器,此时首先开辟空间,然后进行赋值即可.

cpp 复制代码
		vector(int n, const T& val = T())
		{
			//第一种写法
	/*		_start = new T[n];
			_finish = _start + n;
			_end_of_storage = _finish;
			for (size_t i = 0; i < n; i++)
			{
				_start[i] = val;
			}*/
			reserve(n);
			//填充val
			for (size_t i = 0; i < n; i++)
			{
				push_back(val);
			}
		}

可以看到,这个重载函数与之不同的就是其参数n的类型不同,但这却是必要的,否则当我们使用以下代码时,编译器会优先与构造函数3相匹配,甚至无法通过编译

3.3:构造函数3

cpp 复制代码
	//迭代器区间构造,类模板的成员函数可以是函数模板
	//类模板的成员函数可以是函数模板
		template <class InputIterator>
		vector(InputIterator first, InputIterator last)
		{
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}

vector还支持使用一段迭代器区间进行对象的构造。因为该迭代器区间可以是其他容器的迭代器区间,也就是说该函数接收到的迭代器的类型是不确定的,所以我们这里需要将该构造函数设计为一个函数模板,在函数体内将该迭代器区间的数据一个个尾插到容器当中即可。

3.4:拷贝构造函数

3.4.1:第一种写法

cpp 复制代码
		//v2(v1),拷贝构造函数
		vector(const vector<T> & v)
		{
			T* Tmp = new T[v.size()];
			//拷贝数据
			for (size_t i = 0; i < v.size(); i++)
			{
				Tmp[i] = v[i];
			}
			_start = Tmp;
			_finish = _start + v.size();
			_end_of_storage = _start + v.capacity();
		}

对于拷贝构造函数,就是直接开辟一块与该容器大小相同的函数,然后将该容器中的数据一个个拷贝过来即可,然后再更新_finish与_end_of_storage即可.

3.4.2:第二种写法

cpp 复制代码
		//v2(v1),拷贝构造函数
		vector(const vector<T> & v)
		{

			//第二种写法
			reserve(v.capacity());
			for(size_t i = 0; i < v.size(); i++)
			{
				push_back(v[i]);
			}
		}

3.5:赋值运算符重载

cpp 复制代码
		//返回引用的目的是为能够连续赋值
		vector<T>& operator=( vector<T> & v)//赋值运算符重载
		{
			//防止自己给自己赋值
			if(this != &v)
			{
				//释放原有空间
				delete[] _start;
				//开辟新空间
				T* Tmp = new T[v.size()];
				//拷贝数据
				for (size_t i = 0; i < v.size(); i++)
				{
					Tmp[i] = v[i];
				}
				_start = Tmp;
				_finish = _start + v.size();
				_end_of_storage = _start + v.capacity();
			}
			//为支持连续赋值
			return *this;
		}

首先判断是否是给自己赋值,若是给自己赋值则无需进行操作。若不是给自己赋值,则先开辟一块和容器v大小相同的空间,然后将容器v当中的数据进行拷贝,最后更新_finish和_endofstorage的值即可。

3.6:析构函数

cpp 复制代码
	~vector()
	{
		if(_start != nullptr)
		{
			delete[]_start;
			_start = _finish = _end_of_storage = nullptr;
		}
	}

对容器进行析构时,首先判断该容器是否为空容器,若为空容器,则无需进行析构操作,若不为空,则先释放空间,然后将容器的各个成员变量设置为空指针即可。

4:迭代器相关函数

4.1:begin与end

cpp 复制代码
		//迭代器相关函数
		iterator begin()
		{
			return _start;
		}
		iterator end()
		{
			return _finish;
		}
		const_iterator begin() const
		{
			return _start;
		}
		const_iterator end() const
		{
			return _finish;
		}
  • vector当中的begin函数返回容器的首地址,end函数返回容器当中有效数据的下一个数据的地址。
  • 除此之外,还需要对其进行重载,因为存在const对象,所以需要重载begin与end函数,使得const对象能访问到对应的迭代器,但const对象访问到的迭代器只能对数据进行读操作,不能够对其进行修改.

5:容量和大小相关函数

5.1:size与capacity

cpp 复制代码
		//容量相关函数
		size_t size() const
		{
			return _finish - _start;
		}
		size_t capacity() const
		{
			return _end_of_storage - _start;
		}

根据vector中三个成员变量各自的指向,很容易得到当前容器中的有效数据个数和最大容量.

由于两个指针相减的结果,就是两个之间的元素个数,因此

  • size = _start - _end;
  • capacity = _endofstorage - _start;

5.2:reserve

  • 当n > capacity时,此时将capacity扩容到n或者大于n.
  • 当n < capacity时,此时什么也不做.
cpp 复制代码
		//大于capacity时,才会进行扩容
		void reserve(size_t n)
		{
			if(n > capacity() )
			{
				//开辟新空间
				T* Tmp = new T[n];
				size_t oldsize = size();
				//拷贝原有数据
				for(size_t i = 0; i < oldsize; i++)
				{
					Tmp[i] = _start[i];
				}
				//释放旧空间
				delete[]_start;
				_start = Tmp;
				//由于旧空间被释放了,因此要保存旧空间的size,方便finish移动
				_finish = _start + oldsize;
				_end_of_storage = _start + n;
			}
		}
  • 判断n 是否大于capacity.
  • 大于n,首先开辟新空间,并且保留旧空间的有效数据个数.
  • 拷贝原有数据.
  • 释放旧空间,将新开辟的空间交给容器维护.
  • 更新成员变量的值.

5.2.1:拷贝数据问题

有的uu会好奇,为什么在拷贝数据的时候,不使用memcpy去拷贝数据呢?memcpy走的是浅拷贝,可能uu们会想,当vector当中存储的是string的时候**,虽然使用memcpy函数reserve出来的容器与原容器当中每个对应的string成员都指向同一个字符串空间,** 但是原容器存储数据的空间不是已经被释放了,相当于现在只有一个容器维护这这些字符串空间,这还有什么影响呢,可是当释放旧空间的时候,会自动调用string的析构函数,将其指向的字符串也进行释放,

所以使用memcpy函数reserve出来的容器当中的每一个string所指向的字符串实际上是一块已经被释放的空间,访问该容器时就是对内存空间进行非法访问

5.3:resize

  1. 当n < size时,此时将容器的size缩容至n,但不改变capacity.
  2. 当n > size时,此时将size扩大到n,扩大的数据为val,若val未给出,则用0填充.
cpp 复制代码
		void resize(size_t n, const T& val = T())
		{
			if(n < size())
			{
				_finish = _start + n;
			}
			else
			{
				//大于capacity时,才会进行扩容
				if (n > capacity())
				{
					reserve(n);
				}
				while (_finish != _start + n)
				{
					*_finish = val;
					_finish++;
				}
			}
		}

5.4:empty

empty函数可以直接通过比较容器当中的_start和_finish指针的指向来判断容器是否为空,若所指位置相同,则该容器为空。

cpp 复制代码
		bool empty() const
		{
			return _start == _finish;
		}

6:修改容器内容相关函数

6.1:push_back

要尾插数据首先得判断容器是否已满,若已满则需要先进行扩容,然后将数据尾插到_finish指向的位置,再将_finish++即可。

cpp 复制代码
		void push_back(const T& val)
		{
			//先判断容量是否够用
			if(_finish == _end_of_storage)
			{
				size_t newcapacity = capacity() == 0 ? 4 : this->capacity() * 2;
				reserve(newcapacity);
			}
			*_finish = val;
			_finish++;
		}

6.2:pop_back

尾删数据之前也得先判断容器是否为空,若不为空则将_finish--即可。

cpp 复制代码
		void pop_back()
		{
			//确保容器不为空
			if(!empty())
			{
				_finish--;
			}
		}

6.3:insert

insert函数可以在所给迭代器pos位置插入数据,在插入数据前先判断是否需要增容,然后将pos位置及其之后的数据统一向后挪动一位,以留出pos位置进行插入,最后将数据插入到pos位置即可

cpp 复制代码
		void insert(iterator position, const T& val)
		{
			assert(position >= begin() && position <= end());
			//先判断容量是否够用
			if(_finish == _end_of_storage)
			{
				size_t newcapacity = this->capacity() == 0 ? 4 : this->capacity() * 2;
				size_t pos = position - begin();//记录插入位置
				reserve(newcapacity);
				position = begin() + pos;//更新插入位置
			}
			iterator it = _finish - 1;
			//将元素后移
			while(it >= position)
			{
				*(it + 1) = *it;
				it--;
			}
			*position = val;
			_finish++;
		}

若需要增容,则需要在增容前记录pos与_start之间的间隔,然后通过该间隔确定在增容后的容器当中pos的指向,否则pos还指向原来被释放的空间。

6.4:erase

erase函数可以删除所给迭代器pos位置的数据,在删除数据前需要判断容器是否为空,若为空则需做断言处理,删除数据时直接将pos位置之后的数据统一向前挪动一位,将pos位置的数据覆盖即可,

cpp 复制代码
	iterator erase(iterator position)
	{
		assert(!empty());
		iterator it = position + 1;
		//将元素前移
		while(it != _finish)
		{
			//从后往前移
			*(it - 1) = *it;
			it++;
		}
		_finish--;
		return position;
	}

6.5:swap

swap函数用于交换两个容器的数据,我们可以直接调用库当中的swap函数将两个容器当中的各个成员变量进行交换即可。

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

7:访问容器相关函数

cpp 复制代码
		T& operator[](size_t n)
		{
			return _start[n];
		}
		const T& operator[](size_t n) const
		{
			return _start[n];
		}

8:相关测试

8.1:测试默认成员函数

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include "vector.h"

void TestDefaultMemberFunctions()
{
	MyVector::vector<int> v1;
	MyVector::vector<int> v2(10,5);
	MyVector::vector<int> v3;
	v3 = v2;
	MyVector::vector<int> v4(v3);
	MyVector::vector<int> v5(v2.begin(),v2.end());
}

int main()
{
	TestDefaultMemberFunctions();
	return 0;
}

8.2:测试迭代器相关函数

cpp 复制代码
void TestIterator()
{
	MyVector::vector<int> v1(10, 1);
	//使用迭代器遍历
	MyVector::vector<int>::iterator it = v1.begin();
	while (it != v1.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
	//使用const_iterator遍历
	const MyVector::vector<int> v2 = v1;
	for (MyVector::vector<int>::const_iterator it = v2.begin(); it != v2.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

8.3:测试容量与大小相关函数

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include "vector.h"


void TestContainerRelatedFunctions()
{
	MyVector::vector<int> v1;
	cout << "v1 size: " << v1.size() << ", capacity: " << v1.capacity() << ", empty: " << v1.empty() << endl;
	v1.reserve(15);
	cout << "After reserve(15), v1 size: " << v1.size() << ", capacity: " << v1.capacity() << endl;
	v1.resize(10, 3);
	cout << "After resize(10, 3), v1 size: " << v1.size() << ", capacity: " << v1.capacity() << endl;
	for (size_t i = 0; i < v1.size(); i++)
	{
		cout << v1[i] << " ";
	}
	cout << endl;
}

int main()
{
	//TestDefaultMemberFunctions();
	//TestIterator();
	TestContainerRelatedFunctions();
	return 0;
}

8.4:测试尾插与尾删

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include "vector.h"


void TestPushBackAndPopBack()
{
	MyVector::vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	MyVector::vector<int>::iterator it = v1.begin();
	while(it != v1.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;	
	v1.pop_back();
	v1.pop_back();
	it = v1.begin();
	while (it != v1.end())
	{
		cout << *it << " ";
		it++;
	}
}

int main()
{
	TestPushBackAndPopBack();
	return 0;
}

8.5:测试insert与erase与Swap

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include "vector.h"



void TestInsertAndEraseAndSwap()
{
	MyVector::vector<int> v1(8,5);
	v1.insert(v1.begin(), 10);
	v1.insert(v1.begin() + 2, 10);
	v1.insert(v1.end(), 10);
	for (size_t i = 0; i < v1.size(); i++)
	{
		cout << v1[i] << " ";
	}
	cout << endl;
	v1.erase(v1.begin());
	v1.erase(v1.begin() + 1);
	v1.erase(v1.end() - 1);
	for (size_t i = 0; i < v1.size(); i++)
	{
		cout << v1[i] << " ";
	}
	MyVector::vector<int> v2;
	v1.swap(v2);
}



int main()
{
	TestInsertAndEraseAndSwap();
	return 0;
}

9:总代码

9.1:vector.h

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

namespace MyVector 
{
	template <class T>
	class vector
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;
		//默认成员函数
		vector()
			:_start(nullptr)
			,_finish(nullptr)
			,_end_of_storage(nullptr)
		{

		}
		//使用n个val值构造vector
		vector(size_t n, const T& val = T())
		{
			//第一种写法
	/*		_start = new T[n];
			_finish = _start + n;
			_end_of_storage = _finish;
			for (size_t i = 0; i < n; i++)
			{
				_start[i] = val;
			}*/
			reserve(n);
			//填充val
			for (size_t i = 0; i < n; i++)
			{
				push_back(val);
			}
		}

		vector(int n, const T& val = T())
		{
			//第一种写法
	/*		_start = new T[n];
			_finish = _start + n;
			_end_of_storage = _finish;
			for (size_t i = 0; i < n; i++)
			{
				_start[i] = val;
			}*/
			reserve(n);
			//填充val
			for (size_t i = 0; i < n; i++)
			{
				push_back(val);
			}
		}
		//v2(v1),拷贝构造函数
		vector(const vector<T> & v)
		{
			//T* Tmp = new T[v.size()];
			////拷贝数据
			//for (size_t i = 0; i < v.size(); i++)
			//{
			//	Tmp[i] = v[i];
			//}
			//_start = Tmp;
			//_finish = _start + v.size();
			//_end_of_storage = _start + v.capacity();

			//第二种写法
			reserve(v.capacity());
			for(size_t i = 0; i < v.size(); i++)
			{
				push_back(v[i]);
			}
		}

	//迭代器区间构造,类模板的成员函数可以是函数模板
	//类模板的成员函数可以是函数模板
		template <class InputIterator>
		vector(InputIterator first, InputIterator last)
		{
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}


		//返回引用的目的是为能够连续赋值
		vector<T>& operator=( vector<T> & v)//赋值运算符重载
		{
			//防止自己给自己赋值
			if(this != &v)
			{
				//释放原有空间
				delete[] _start;
				//开辟新空间
				T* Tmp = new T[v.size()];
				//拷贝数据
				for (size_t i = 0; i < v.size(); i++)
				{
					Tmp[i] = v[i];
				}
				_start = Tmp;
				_finish = _start + v.size();
				_end_of_storage = _start + v.capacity();
			}
			//为支持连续赋值
			return *this;
		}
		~vector()
		{
			if(_start != nullptr)
			{
				delete[]_start;
				_start = _finish = _end_of_storage = nullptr;
			}
		}

		//迭代器相关函数
		iterator begin()
		{
			return _start;
		}
		iterator end()
		{
			return _finish;
		}
		const_iterator begin() const
		{
			return _start;
		}
		const_iterator end() const
		{
			return _finish;
		}

		//容量相关函数
		size_t size() const
		{
			return _finish - _start;
		}
		size_t capacity() const
		{
			return _end_of_storage - _start;
		}

		//大于capacity时,才会进行扩容
		void reserve(size_t n)
		{
			if(n > capacity() )
			{
				//开辟新空间
				T* Tmp = new T[n];
				size_t oldsize = size();
				//拷贝原有数据
				for(size_t i = 0; i < oldsize; i++)
				{
					Tmp[i] = _start[i];
				}
				//memcpy的本质是浅拷贝
				//memcpy(Tmp,_start,size() * sizeof(T));
				//释放旧空间
				delete[]_start;
				_start = Tmp;
				//由于旧空间被释放了,因此要保存旧空间的size,方便finish移动
				_finish = _start + oldsize;
				_end_of_storage = _start + n;
			}
		}
		void resize(size_t n, const T& val = T())
		{
			if(n < size())
			{
				_finish = _start + n;
			}
			else
			{
				//扩容
				reserve(n);
				//填充val
				while (_finish != _start + n)
				{
					*_finish = val;
					_finish++;
				}
			}
		}

		bool empty() const
		{
			return _start == _finish;
		}
		
		//元素访问相关函数
		T& operator[](size_t n)
		{
			return _start[n];
		}
		const T& operator[](size_t n) const
		{
			return _start[n];
		}

		//修改容器相关函数
		void push_back(const T& val)
		{
			//先判断容量是否够用
			/*if(_finish == _end_of_storage)
			{
				size_t newcapacity = capacity() == 0 ? 4 : this->capacity() * 2;
				reserve(newcapacity);
			}
			*_finish = val;
			_finish++;*/
			insert(end(), val);

		}
		void pop_back()
		{
			//确保容器不为空
			if(!empty())
			{
				_finish--;
			}
		}
		void insert(iterator position, const T& val)
		{
			assert(position >= begin() && position <= end());
			//先判断容量是否够用
			if(_finish == _end_of_storage)
			{
				size_t newcapacity = this->capacity() == 0 ? 4 : this->capacity() * 2;
				size_t pos = position - begin();//记录插入位置
				reserve(newcapacity);
				position = begin() + pos;//更新插入位置
			}
			iterator it = _finish - 1;
			//将元素后移
			while(it >= position)
			{
				*(it + 1) = *it;
				it--;
			}
			*position = val;
			_finish++;
		}
		iterator erase(iterator position)
		{
			assert(!empty());
			iterator it = position + 1;
			//将元素前移
			while(it != _finish)
			{
				//从后往前移
				*(it - 1) = *it;
				it++;
			}
			_finish--;
			return position;
		}
		void swap(vector <T>& v1)
		{
			std::swap(_start, v1._start);
			std::swap(_finish, v1._finish);
			std::swap(_end_of_storage, v1._end_of_storage);
		}
	private:
		iterator _start = nullptr;//指向数组起始位置
		iterator _finish = nullptr;//指向数组最后一个元素的下一个位置
		iterator _end_of_storage = nullptr; //指向数组的最后位置
	};
}

9.2:Test.cpp

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include "vector.h"

void TestDefaultMemberFunctions()
{
	MyVector::vector<int> v1;
	MyVector::vector<int> v2(10,5);
	MyVector::vector<int> v3;
	v3 = v2;
	MyVector::vector<int> v4(v3);
	MyVector::vector<int> v5(v2.begin(),v2.end());
}

void TestIterator()
{
	MyVector::vector<int> v1(10, 1);
	//使用迭代器遍历
	MyVector::vector<int>::iterator it = v1.begin();
	while (it != v1.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
	//使用const_iterator遍历
	const MyVector::vector<int> v2 = v1;
	for (MyVector::vector<int>::const_iterator it = v2.begin(); it != v2.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void TestContainerRelatedFunctions()
{
	MyVector::vector<int> v1;
	cout << "v1 size: " << v1.size() << ", capacity: " << v1.capacity() << ", empty: " << v1.empty() << endl;
	v1.reserve(15);
	cout << "After reserve(15), v1 size: " << v1.size() << ", capacity: " << v1.capacity() << endl;
	v1.resize(10, 3);
	cout << "After resize(10, 3), v1 size: " << v1.size() << ", capacity: " << v1.capacity() << endl;
	for (size_t i = 0; i < v1.size(); i++)
	{
		cout << v1[i] << " ";
	}
	cout << endl;
}



void TestPushBackAndPopBack()
{
	MyVector::vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	MyVector::vector<int>::iterator it = v1.begin();
	while(it != v1.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;	
	v1.pop_back();
	v1.pop_back();
	it = v1.begin();
	while (it != v1.end())
	{
		cout << *it << " ";
		it++;
	}

}

void TestInsertAndEraseAndSwap()
{
	MyVector::vector<int> v1(8,5);
	v1.insert(v1.begin(), 10);
	v1.insert(v1.begin() + 2, 10);
	v1.insert(v1.end(), 10);
	for (size_t i = 0; i < v1.size(); i++)
	{
		cout << v1[i] << " ";
	}
	cout << endl;
	v1.erase(v1.begin());
	v1.erase(v1.begin() + 1);
	v1.erase(v1.end() - 1);
	for (size_t i = 0; i < v1.size(); i++)
	{
		cout << v1[i] << " ";
	}
	MyVector::vector<int> v2;
	v1.swap(v2);
}




int main()
{
	//TestDefaultMemberFunctions();
	//TestIterator();
	//TestContainerRelatedFunctions();
	//TestMemcpy();
	//TestPushBackAndPopBack();
	TestInsertAndEraseAndSwap();
	return 0;
}
相关推荐
小年糕是糕手2 小时前
【C++】内存管理(下)
java·c语言·开发语言·数据结构·c++·算法
艾莉丝努力练剑2 小时前
【Linux基础开发工具 (六)】Linux中的第一个系统程序——进度条Linux:详解回车、换行与缓冲区
java·linux·运维·服务器·c++·centos
ZouZou老师2 小时前
C++设计模式之单例模式:以小区快递柜为例
c++·单例模式·设计模式
蜗牛love天空2 小时前
qt窗口机制和mfc窗口机制
c++
定义小花2 小时前
c++ cmake qt
开发语言·c++·qt
草莓熊Lotso2 小时前
哈希表的两种灵魂:深入探索开放定址与链地址法的核心机密
linux·运维·数据结构·c++·人工智能·算法·哈希算法
赖small强2 小时前
【Linux C/C++开发】Linux C/C++编译参数 `-fPIC` 深度解析
linux·c语言·c++
小年糕是糕手2 小时前
【C++】内存管理(上)
java·开发语言·jvm·c++·算法·spring·servlet
csdn_aspnet2 小时前
C++ 长方体表面积和体积计算程序(Program for Surface Area and Volume of Cuboid)
c++