2024年最新C++入门 vector的使用 + 进阶【模拟实现】_c(2),2024年最新2024年华为网络安全面试真题解析

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上网络安全知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以点击这里获取

目录

基本接口函数介绍

函数名功能
vector()(重点)无参构造,构造一个空容器,没有元素。
vector(size_type n, const value_type& val = value_type())构造并初始化n个val
vector (const vector& x); (重点)拷贝构造
vector (InputIterator first, InputIterator last);使用迭代器进行初始化构造

测试:

void func() 
{
	int arr[] = {8,4,3,6,1};
	vector<int> vc;//构造一个空容器,没有元素
	vector<int> vc1(10,5);//构造并初始化n个val
	vector<int> vc2(vc1);//拷贝构造
	//使用迭代器进行初始化构造
	vector<int> vc3(arr ,arr + sizeof(arr) / sizeof(arr[0]));

	test(vc);
	test(vc1);
	test(vc2);
	test(vc3);
	//test(vc);
}

测试效果
在这里插入图片描述

调用不带参数的构造函数,成员属性初始值值会给0
在这里插入图片描述

迭代器

迭代器分类

iterator的使用接口说明
begin +end(重点)获取第一个数据位置的iterator/const_iterator, 获取最后一个数据的下一个位置
rbegin + rend获取最后一个数据位置的reverse_iterator,获取第一个数据前一个位置的

在这里插入图片描述

//使用正向迭代器
void test1(vector<int> &v) 
{
	vector<int>::iterator it = v.begin();
	while (it != v.end()) 
	{
		cout << \*it++ << " ";
	}	
	cout << endl;
}
//使用反向迭代器
void test2(vector<int>& v)
{
	vector<int>::reverse_iterator it = v.rbegin();
	while (it != v.rend())
	{
		cout << \*it++ << " ";
	}
	cout << endl;
}

空间容量

容量空间接口说明
size获取数据个数
capacity获取容量大小
empty判断是否为空

resize(重点)

1、调整容器大小,使其包含n个元素。
2、如果n小于当前容器的大小,则将内容减少到其前n个元素,并删除(并销毁)超过的元素。
3、如果n大于当前容器的大小,则在容器的末尾插入足够多的元素来扩展容器的内容,使容器的大小达到n。如果指定了val,则将新元素初始化为val的副本,否则将对它们进行值初始化。

reserve (重点)

请求向量容量至少足以容纳n个元素。
如果n大于当前的容量,该函数将导致容器重新分配其存储空间,将其容量增加到n(或更大)。
在所有其他情况下,函数调用不会导致重新分配,vector容量也不会受到影响。 也不能改变它的元素。

1、capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的。这个问题经常会考察,不要固化的认为,顺序表增容都是2倍,具体增长多少是根据具体的需求定义的。vs是PJ版本STL,g++是SGI版本STL。

2、reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题。

3、resize在开空间的同时还会进行初始化,影响size

用一份测试代码去观察:

void func1() 
{
	vector<int> v;
	int size = v.capacity();
	cout << size << endl;
	for (int i = 0; i < 100; i++) 
	{
		v.push\_back(i);
		if (v.capacity() != size)
		{
			size = v.capacity();
			cout << "扩容后:" << size << endl;
		}
	}
}

vs下capacity是按1.5倍增长的
在这里插入图片描述

在linux下以2倍增长
在这里插入图片描述

增删查改

vector增删查改接口说明
push_back(重点)尾插
pop_back (重点)尾删
find查找。(注意这个是算法模块实现,不是vector的成员接口)
insert在position之前插入val
erase删除position位置的数据
swap交换两个vector的数据空间
operator[] (重点)返回此下标位置的值
void func1() 
{
	//插入5个值
	vector<int> v;
	v.push\_back(1);
	v.push\_back(2);
	v.push\_back(3);
	v.push\_back(4);
	v.push\_back(5);
	
	for (auto val : v) 
	{
		cout << val << " ";
	}
	cout << endl;
	//在一段迭代去区间查找值为2的元素,找到返回此位置的迭代器,
	//没有找到就返回end()处的迭代器
	vector<int>::iterator pos = find(v.begin(),v.end(),2);
	if (pos != v.end()) 
	{
		//将值插入到pos位置之前
		v.insert(pos,30);
	}
	
	for (auto val : v)
	{
		cout << val << " ";
	}
	cout << endl;
	//在一段迭代去区间查找值为2的元素,找到返回此位置的迭代器,
	//没有找到就返回end()处的迭代器
	pos = find(v.begin(), v.end(), 30);
	if (pos != v.end()) 
	{
		//删除pos位置的值
		v.erase(pos);
	}
	
	for (auto val : v)
	{
		cout << val << " ";
	}
	
}

迭代器失效问题探讨

野指针问题

//测试二
void func2() 
{
	vector<int> v;
	v.push\_back(1);
	v.push\_back(2);
	v.push\_back(3);
	v.push\_back(4);
	v.push\_back(5);
	
	vector<int>::iterator it = v.begin();
	while (it != v.end()) 
	{
		cout << \*it << " ";
		it++;
	}
	cout << endl;
	//查找 pos位置,找到后返回此位置的迭代器
	vector<int>::iterator pos = find(v.begin(), v.end(), 3);
	//在pos位置前插入10,空间会扩容并释放旧的空间,
	//重新分配一块新的空间,由于旧空间已经被释放完了,所以不可访问
	v.insert(pos,10);
	it = v.begin();
	while (it != v.end())
	{
		cout << \*it << " ";
		it++;
	}
	
	cout << endl;
	//pos是野指针,使用pos去访问旧空间是一个隐患
	v.erase(pos);
	it = v.begin();
	while (it != v.end())
	{
		cout << \*it << " ";
		it++;
	}

}

这个程序的运行是会存在错误的,错误的原因是pos还在访问那块旧的空间,pos迭代器却早已经失效了,旧空间释放后内存使用权限已经归还给操作系统了,而pos还指向那块旧的空间,v.erase(pos);这句代码就是去访问一块非法内存,所以就会程序崩溃
在这里插入图片描述
图解:
在这里插入图片描述

下面这块程序的功能是将容器中所有的偶数都删除掉,只保留奇数数据
这段程序在不同的平台上是不一样的

//测试一
void func1() 
{
	vector<int> v;
	v.push\_back(1);
	v.push\_back(2);
	v.push\_back(3);
	v.push\_back(4);
	v.push\_back(5);
	v.push\_back(6);
	//v.push\_back(7);
	
	vector<int>::iterator it = v.begin();
	while (it != v.end())
	{
		if (\*it % 2 == 0) 
		{
			v.erase(it);
		}
		it++;
	}
	for (auto e : v) 
	{
		cout << e << " ";
	}
}

在vs上,程序就直接崩溃了
在这里插入图片描述
在linux上出现段错误
在这里插入图片描述
图解析:
在这里插入图片描述
从图中我们可以看出it每次删元素的时候都会跳过一个元素,end的位置每次也都在发生变化,直到删除6的时候 it 和 end已经开始错开了,分道扬镳,此后再也不会相遇,it此时就是野指针了,访问了一块非法的内存,但是在linux上平台上我们只需要将尾插一个7(奇数)就能解决这个问题,vs下无论是最后一个值是奇数还是偶数都会报错,it已经失效,编译器会直接对it++检查
在这里插入图片描述
是因为当插入7的时候刚好检查到最后一个位置不会再erase掉,it再往后迭代的时候就遇到了end,循环也就终止了,但是这段代码还是错误的代码,因为不同的平台跑出的结果是不一样的

解决方案

vector<int>::iterator it = v.begin();
	while (it != v.end())
	{
		if (\*it % 2 == 0)
		{
			//erase删除it位置的元素后,会返回it位置的下一个位置,
			//再回去检查这个元素是否是偶数
			it = v.erase(it);
		}
		else 
		{
			it++;
		}	
	}

总结:
insert和erase都会导致迭代器失效
1、insert(it, x) 或者 erase(it) 以后迭代器的意义变了
2、insert(it, x) 或者 erase(it) 以后it变成了野指针

vector模拟实现

namespace mzt 
{
	template<class T>
	class vector
	{
	public:
		typedef T\* iterator;
		iterator begin() { return _start; }
		iterator end() { return _finish; }
		size_t capacity() { return _endofstroage - _start; }
		size_t size() { return _finish - _start; }

		vector()
			:\_start(nullptr)
			, \_finish(nullptr)
			, \_endofstroage(nullptr)
		{ }
		vector(vector<T>& v)
			:\_start(nullptr)
			,\_finish(nullptr)
			,\_endofstroage(nullptr)
		{
			reserve(v.capacity());
			for (auto &e : v) 
			{
				push\_back(e);
			}
		}

		void swap(vector<T>& v)
		{
			::swap(_start,v._start);
			::swap(_finish,v._finish);
			::swap(_endofstroage,v._endofstroage);
		}
		vector<T>& operator=(vector<T> v)
		{
			if (this != &v) 
			{
				swap(v);
			}
			return \*this;
		}

		void reserve(size_t n) 
		{
			size_t sz = size();
			T\* tmp = new T[n];
			if (n > capacity())
			{
				//memcpy(tmp,\_start,sizeof(T) \* n);
				if (_start)
				{
					for (size_t i = 0; i < sz; i++)
					{
						tmp[i] = _start[i];
					}
					delete[]_start;
				}

				_start = tmp; 
				_finish = _start + sz;
				_endofstroage = _start + n;
			}
		}
		//尾插
		void push\_back(const T& v)
		{
			if (_finish == _endofstroage)
			{
				size_t newcapacity = capacity() == 0 ? 4 : capacity() \* 2;
				reserve(newcapacity);
			}
			\*_finish++ = v;
		}
		void erase() 
		{
			assert(!empty());
			--_finish;
		}

		void resize(size_t n,T a = T()) 
		{
			if (n < capacity()) 
			{
				_finish = _start + n;
			}
			else 
			{
				if (n > capacity()) 
				{
					reserve(n);
				}
				while (_finish < _endofstroage) 
				{
					\*_finish++ = a;
				}
			}
		}
		size_t operator[](size_t n) 
		{
			assert(n < size());
			return _start[n];
		}
	
		iterator insert(iterator pos, const T& x)
		{
			if (_finish == _endofstroage) 
			{
				size_t len = pos - _start;
				size_t newcapacity = capacity() == 0 ? 4 : capacity() \* 2;
				reserve(newcapacity);
				//pos失效后重新计算pos的位置
				pos = _start + len;
			}
			iterator end = _finish - 1;
			while (end >= pos) 
			{
				\*(end + 1) = \*end;
				end--;
			}	
			\*pos = x;
			++_finish;
			return pos;
		}
		iterator erase(iterator pos)
		{
			assert(!empty());
			iterator it = pos + 1;
			while (it != _finish) 
			{
				\*(it - 1) = \*it;
				it++;
			}
			--_finish;
			return pos;
		}

		bool empty() { return _start == _finish; }

		~vector() 
		{
			if (_start) 
			{
				delete[] _start;
			}
			_start = _finish = _endofstroage = __nullptr;
		}

	private:
		iterator _start;
		iterator _finish;
		iterator _endofstroage;
	};


}

私有成员

iterator _start;//返回起始位置
iterator _finish;//返回最后一个元素的下一个位置


### 给大家的福利


**零基础入门**


对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。


![](https://img-blog.csdnimg.cn/img_convert/95608e9062782d28f4f04f821405d99a.png)


同时每个成长路线对应的板块都有配套的视频提供:


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/a91b9e8100834e9291cfcf1695d8cd42.png#pic_center)


因篇幅有限,仅展示部分资料

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化资料的朋友,可以点击这里获取](https://bbs.csdn.net/topics/618540462)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

ish;//返回最后一个元素的下一个位置


### 给大家的福利


**零基础入门**


对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。


![](https://img-blog.csdnimg.cn/img_convert/95608e9062782d28f4f04f821405d99a.png)


同时每个成长路线对应的板块都有配套的视频提供:


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/a91b9e8100834e9291cfcf1695d8cd42.png#pic_center)


因篇幅有限,仅展示部分资料

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化资料的朋友,可以点击这里获取](https://bbs.csdn.net/topics/618540462)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 28
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值