1、vector迭代器失效问题。

 迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对指针进行了封装,比如:vector的迭代器就是原生态指针T* 。因此迭代器失效,实际就是迭代器底层对应指针所指向的空间被销毁了,而使用一块已经被释放的空间,造成的后果是程序崩溃(即如果继续使用已经失效的迭代器,程序可能会崩溃)。

void  test4()
{
	vector<int>v{ 1,2,3,4,5,6 };
	vector<int>::iterator it = v.begin();
	// 将有效元素个数增加到100个,多出的位置使用8填充,操作期间底层会扩容
	v.resize(100, 8);

	 // reserve的作用就是改变扩容大小但不改变有效元素个数,操作期间可能会引起底层容量改变
	v.reserve(100);

	 // 插入元素期间,可能会引起扩容,而导致原空间被释放
	v.insert(v.begin(), 0);
	v.push_back(8);

	 // 给vector重新赋值,可能会引起底层容量改变
	v.assign(100, 8);

	/*
	出错原因:以上操作,都有可能会导致vector扩容,也就是说vector底层原理旧空间被释放掉,
	而在打印时,it还使用的是释放之间的旧空间,在对it迭代器操作时,实际操作的是一块已经被释放的
	空间,而引起代码运行时崩溃。
	解决方式:在以上操作完成之后,如果想要继续通过迭代器操作vector中的元素,只需给it重新
	赋值即可。
	*/
	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
}

2、指定位置元素的删除操作–erase

void test5()
{
	int a[] = { 1,2,3,4 };
	vector<int>v(a, a + sizeof(a) / sizeof(int));
	//找到3的地址
	vector<int>::iterator pos = find(v.begin(), v.end(), 3);
	v.erase(pos);
	//vs删除的元素的地址不让访问,非法访问
	cout << (*pos) << endl;
}

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

3、杨辉三角

alt

class Solution {
public:
    vector<vector<int>> generate(int numRows) 
    {
        vector<vector<int>>vv1;
        vv1.resize(numRows);
        for(size_t i = 0;i<numRows;i++)
        {
            (vv1[i]).resize(i+1);
        }
        for(size_t j = 0;j<vv1[i].size();j++)
            {
                if((j==0)||(j==vv1[i].size()-1))
                {
                    vv1[i][j] = 1;
                }
                else if(!((i==0)&&(i==1)))
                {
                    vv1[i][j] = vv1[i-1][j]+vv1[i-1][j-1];
                }
            }
        return vv1;
    }
};

 vector<vector>vv(n), 构造一个vv动态二维数组,vv中总共有n个元素,每个元素都是vector类型的,每行没有包含任何元素,如果n为5时如下所示:
alt

 vv中元素填充完成之后,如下图所示:

4、使用memcpy造成浅拷贝问题

int main()
{
	wyj::vector<string> v;
	v.pushback("1111");
	v.pushback("2222");
	v.pushback("3333");
	v.pushback("4444");
	v.pushback("5555");
	return 0;
}

1. memcpy是内存的二进制格式拷贝,将一段内存空间中内容原封不动的拷贝到另外一段内存空间中
2. 如果拷贝的是内置类型的元素,memcpy既高效又不会出错,但如果拷贝的是自定义类型元素,并且自定义类型元素中涉及到资源管理时,就会出错,因为memcpy的拷贝实际是浅拷贝。

alt
alt
alt
alt

 如果对象中涉及到资源管理时,千万不能使用memcpy进行对象之间的拷贝,因为memcpy是浅拷贝,否则可能会引起内存泄漏甚至程序崩溃。

 基于上面一些问题,reserve扩容时,直接进行手动赋值,如果是自定义类型,他就会自己调用自己的赋值函数,进行深拷贝,就解决了这个问题


		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());
					//memcpy浅拷贝,不行,不能对自定义类型进行拷贝
					for (size_t i = 0; i < oldsize; i++)
					{
						//自定义类型会调用自己的拷贝构造来自己进行深拷贝
						//内置类型更是没的说,直接赋值
						//这儿是赋值,不是拷贝构造
						tmp[i] = _start[i];
						//std::swap(tmp[i], _start[i]);
					}
					delete[] _start;
				}
				_start = tmp;
				//重新申请空间,会导致三个指针的变化
				//_start = tmp;已经更新了
				//但是_finish还是指向原来的空间,但是原来的空间已经释放
				//因此,要提前保存好_start到_finish的距离,更新_finish
				_finish = _start + oldsize;
				_end_of_storage = _start + n;
			}
		}
#define  _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <assert.h>
#include <list>
using namespace std;
//用模版写,建议声明定义放到一个文件里面
//理由:以后说

namespace wyj
{
	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)
			{
				pushback(*first);
				first++;
			}
		}
		
		//T()匿名对象,调用默认拷贝构造生成一个匿名对象赋值给val
		//把n个T对象插入vector
		vector(size_t n, const T& val = T())  //T()匿名对象
		{
			reserve(n);
			for (size_t i = 0; i < n; i++)
			{
				pushback(val);
			}
		}

		//解决int,int 匹配问题
		vector(int n, const T& val = T())  //T()匿名对象
		{
			reserve(n);
			for (size_t i = 0; i < n; i++)
			{
				pushback(val);
			}
		}

		vector(initializer_list<T>il) 
		{
			reserve(il.size());
			for (auto& e:il)
			{
				pushback(e);
			}
		}
		//编译器强制生成默认的
		vector() = default;
		vector(const vector<T>& v)
		{
			reverse(v.size());
			for (auto& e : v)
			{
				pushback(e);
			}
		}

		void swap(vector<T>& v)
		{
			std:swap(_start, v._start);
			std:swap(_finish, v._finish);
			std:swap(_end_of_storage, v._start_of_storage);
		}

		//vector<T>v 这是拷贝了一份
		vector<T> operator=(vector<T> v)
		{
			this->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) * size());
					//memcpy浅拷贝,不行,不能对自定义类型进行拷贝
					for (size_t i = 0; i < oldsize; i++)
					{
						//自定义类型会调用自己的拷贝构造来自己进行深拷贝
						//内置类型更是没的说,直接赋值
						
						tmp[i] = _start[i];
						//std::swap(tmp[i], _start[i]);
					}
					delete[] _start;
				}
				_start = tmp;
				//重新申请空间,会导致三个指针的变化
				//_start = tmp;已经更新了
				//但是_finish还是指向原来的空间,但是原来的空间已经释放
				//因此,要提前保存好_start到_finish的距离,更新_finish
				_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 pushback(const T& x)
		{
			if (_finish == _end_of_storage)
			{
				size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
				reserve(newcapacity);
			}
			*_finish = x;
			++_finish;
			//insert(end(), x);
		}
		void popback()
		{
			assert(size());
			--_finish;
		}
		//下面这个不行
		//void insert(iterator pos, const T& x)
		//iterator pos这个传的是地址,若扩容,则地址变化
		iterator  insert(iterator pos, const T& x)
		{
			assert(pos >= _start && pos <= _finish);
			if (_finish == _end_of_storage)
			{
				//空间问题
				size_t len = pos - _start;
				size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
				reserve(newcapacity);
				//这儿pos的地址虽然更新了,但是外面的pos没有变化
				pos = _start + len;
			}
			iterator end = _finish;
			while (end>pos)
			{
				*end = *(end - 1);
				end--;
			}
			*pos = x;
			_finish++;
			return pos;
		}
		void erase(iterator pos)
		{
			assert(pos >= _start && pos < _finish);
			iterator it = pos + 1;
			while (it < _finish)
			{
				*(it - 1) = *it;
				it++;
			}
			_finish--;
		}
	private:
		iterator _start = nullptr;  //指向第一个数据
		iterator _finish = nullptr; //指向最后一个数据的下一个
		iterator _end_of_storage = nullptr; 
	};

	void test_vector1()
	{
		vector<int> v1;
		v1.pushback(1);
		v1.pushback(2);
		v1.pushback(3);
		v1.pushback(4);
		v1.pushback(5);
		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 it1 = v1.begin();
		while (it1 != v1.end())
		{
			cout << *it1 << " ";
			it1++;
		}
		cout << endl;
	}

	void test_vector2()
	{
		vector<int> v1;
		v1.pushback(1);
		v1.pushback(2);
		v1.pushback(3);
		v1.pushback(4);
		//找出4的地址
		vector<int> ::iterator it = find(v1.begin(), v1.end(), 4);
		//在4后面插入5
		//会发生扩容,it指向的地址已经变化
		//外面访问不到
		//迭代器失效
		v1.insert(it + 1, 5);
		for (auto& e : v1)
		{
			cout << e << " ";
		}
		cout << endl;
		//it是原来的地址,在扩容中空间已经更新了
		//用原来的地址访问不到。
		//迭代器失效
		cout << *(it + 1) << endl;
		cout << endl;
	}
	void test_vector3() 
	{
		vector<int> v1;
		v1.pushback(1);
		v1.pushback(2);
		v1.pushback(3);
		v1.pushback(4);
		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;
		vector<int>::iterator it = v1.begin();
		v1.erase(v1.begin());
		cout << (*it) << endl;
		for (auto e : v1)
		{
			cout << e << " ";
		}

		cout << endl;
	}
	void test_vector4()
	{
		std::vector<int>v1;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		std::vector<int> ::iterator it = find(v1.begin(),v1.end(),3);
		//删除了3
		if (it != v1.end())
		{
			it = v1.erase(it);
		}
		//迭代器失效
		if (it != v1.end())
		{
			cout << (*it) << endl;
		}
		for (auto e : v1)
		{
			cout << e << " ";
		}
	}

	void test_vector5()
	{
		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 ((*it) % 2 == 0)
			{
				it = v1.erase(it);
			}
			else
			{
				++it;
			}
		}
		for (auto e : v1)
		{
			cout << e << " ";
		}
	}
	void test_vector6()
	{
		vector<int> v1;
		v1.pushback(1);
		v1.pushback(2);
		v1.pushback(3);
		v1.pushback(4);
		v1.pushback(5);
		vector<int>v2(v1.begin()+1,v1.end()-1);
		for (auto e : v2)
		{
			cout << e << " ";
		}
		cout << endl;
		string s1("helloworld");
		vector<int> v3(s1.begin(),s1.end());
		for (auto e : v3)
		{
			cout << e << " ";
		}
		cout << endl;
		//vector<int>v4(3, 4);
		//for (auto e : v4)
		//{
		//	cout << e << " ";
		//}

		std::list<int> l;
		l.push_back(100);
		l.push_back(100);
		l.push_back(100);
		l.push_back(100);
		vector<int>v5(l.begin(),l.end());
		for (auto e : v5)
		{
			cout << e << " ";
		}
	}

	void test_vector7()
	{
		//C++对内置类型进行升级,也有了构造
		int a = int();  //0
		int b(1);  //1
		int c = int(10);  //10

		//string 默认构造为空字符串
		vector<string>v1(10);
		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;
		vector<string>v2(10,"xxx");
		for (auto e : v2)
		{
			cout << e << " ";
		}
		cout << endl;
		//u代表unsigned int 
		/*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, int a2)
			:_a1(a1)
			,_a2(a2)
		{}
		A(int a1 = 0)
			:_a1(a1)
			, _a2(0)
		{}
	private:
		int _a1;
		int _a2;
	};

	void test_vector8()
	{
		//单参数和多参数隐式类型转换
		//省略赋值符号
		A aa1(1, 2);
		A aa2 = { 1,2 };
		A aaa2{ 1,2 };  //不要
		const A& aa8 = { 1,2 };

		A aa3(1);
		A aa4 = 1;

		A aa5(1);
		A aa6 = {1}; //不要
		A aa7{ 1 };  //不要

		//std支持
		//自己写的不支持
		//这里不是隐式类型转换
		vector<int> v1 = { 1,2,3,3,5 };
		vector<int> v2 = { 1,2,3 };
		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;
		auto l1 = { 1,2,3,4,5 };
		//class std::initializer_list<int>
		initializer_list<int> l2 = { 1,2,3 };
		cout << typeid(initializer_list<int>).name() << endl;
		cout << sizeof(l2) << endl;  //x64下  16个字节

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

	void test_vector9()
	{
		vector<string>v1;
		v1.pushback("11111111111111111111111\n");
		v1.pushback("11111111111111111111111\n");
		v1.pushback("11111111111111111111111\n");
		v1.pushback("11111111111111111111111\n");
		//大坑
		v1.pushback("11111111111111111111111");
		for (auto e : v1)
		{
			cout << e << " ";
		}
	}
}


#include "vector.h"

//namespace wyj 
//{
//	template<class T>
//	class vector
//	{
//	private:
//		T* _a;
//		size_t _size;
//		size_t _capacity;
//	};
//}

void test_vector1()
{
	//string 
	//vector<char> 
	//
	vector<string> v3;
	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中定义的,要指明来处
	vector<int> :: iterator it1 = v1.begin();
	while (it1 != v1.end())
	{
		cout << (*it1) << " ";
		it1++;
	}
	cout << endl;
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;
}

//void push_back(const string& s)
//{}
void test_vector2()
{
	vector<string> v1;
	string s1("张三");
	v1.push_back(s1);
	v1.push_back(string("李四"));
	v1.push_back("王五");
	v1[0] += "猪";
	for (const auto& e : v1)
	{
		cout << e << " ";
	}
	cout << endl;
	cout << v1.front() << endl;
	cout << v1.back() << endl;
}

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;
	//默认是升序
	//传gt,降序,具体为什么,不知道
	//sort(v1.begin(), v1.end(),gt);
	// 一般这么用
	//greater<int>() -->传匿名对象
	sort(v1.begin(), v1.end(), greater<int>());
	//sort(v1.begin(), v1.begin() + v1.size() / 2);
	for (auto e : v1)
	{
		cout << e << " ";
	}
}

void test1()
{
	char str[] = { 'h','e','l','l','o','w' };
	char* pstr1 = &str[0];
	char* pstr2 = &str[3];
	cout << pstr2 - pstr1 << endl; //3
}

void test2()
{
	vector<string> v1;
	v1.push_back("HelloWorld");
	cout << v1[0] << endl;
}

void test3()
{
	vector<int>v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	//删除2,先记住2的地址
	vector<int> ::iterator it = v1.begin() + 1;
	v1.erase(it);
	//在访问保存的这个地址
	cout << (*it) << endl;
} 

void  test4()
{
	vector<int>v{ 1,2,3,4,5,6 };
	vector<int>::iterator it = v.begin();
	// 将有效元素个数增加到100个,多出的位置使用8填充,操作期间底层会扩容
	v.resize(100, 8);

	 // reserve的作用就是改变扩容大小但不改变有效元素个数,操作期间可能会引起底层容量改变
	v.reserve(100);

	 // 插入元素期间,可能会引起扩容,而导致原空间被释放
	v.insert(v.begin(), 0);
	v.push_back(8);

	 // 给vector重新赋值,可能会引起底层容量改变
	v.assign(100, 8);

	/*
	出错原因:以上操作,都有可能会导致vector扩容,也就是说vector底层原理旧空间被释放掉,
	而在打印时,it还使用的是释放之间的旧空间,在对it迭代器操作时,实际操作的是一块已经被释放的
	空间,而引起代码运行时崩溃。
	解决方式:在以上操作完成之后,如果想要继续通过迭代器操作vector中的元素,只需给it重新
	赋值即可。
	*/
	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
}

void test5()
{
	int a[] = { 1,2,3,4 };
	vector<int>v(a, a + sizeof(a) / sizeof(int));
	//找到3的地址
	vector<int>::iterator pos = find(v.begin(), v.end(), 3);
	v.erase(pos);
	//vs删除的元素的地址不让访问,非法访问
	cout << (*pos) << endl;
}

//int main()
//{
//	//wyj::test_vector4();
//	//string s1("helloworld");
//	//reverse(s1.begin(), s1.end());
//	//cout << s1 << endl;
//	//test();
//	//wyj::test_vector9();
//	test5();
//	return 0;
//}

int main()
{
	wyj::vector<string> v;
	v.pushback("1111");
	v.pushback("2222");
	v.pushback("3333");
	v.pushback("4444");
	v.pushback("5555");
	return 0;
}









Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐