模拟实现list和vector反向迭代器

news2024/12/28 19:34:11

学习这部分知识,需要你了解vector和list的正向迭代器知识以及容器适配器知识,可以阅读我写的另外三篇vector、list、容器适配器 知识的博客!其中list知识内容尤其重要且难度要求很高!

反向迭代器,顾名思义是与正向迭代器相对,作用是反向遍历容器数据!

目录

一、反向迭代器

1.1 反向迭代器相关函数

1.1.1 rbegin() 

 1.1.2 rend() 

1.2反向迭代器反向遍历vector和list

1.2.1 反向遍历vector

1.2.2 反向遍历list

 二、模拟实现vector反向迭代器

2.1 vector正向迭代器

2.2 vector反向迭代器

2.3 模拟测试遍历vector

2.3.1 const反向迭代器效果

2.3.2  反向迭代器遍历

三、模拟实现list反向迭代器

3.1 list 正向迭代器

3.2 模拟实现list反向迭代器

3.3 测试反向迭代器遍历 

3.3.1 const迭代器效果展示

3.3.2 反向迭代器遍历list

 四、模拟实现vector完整版

五、模拟实现list完整版


一、反向迭代器

1.1 反向迭代器相关函数

C++11中加了独立的返回const迭代器的函数,但这篇博客只模拟实现list的const函数重载来返回const迭代器! 具体这些函数请查看cplusplus.com - The C++ Resources Network

1.1.1 rbegin() 

返回值:返回指向容器中最后一个元素(即其反向开头)的反向迭代器!

const修饰的函数返回值:返回const反向迭代器,其指向成员不能被修改!

 1.1.2 rend() 

返回值:返回一个反向迭代器,该迭代器指向容器中第一个元素之前的理论元素

const修饰的函数返回值:返回const反向迭代器,其指向成员不能被修改!

1.2反向迭代器反向遍历vector和list

1.2.1 反向遍历vector

1.2.2 反向遍历list


 二、模拟实现vector反向迭代器

2.1 vector正向迭代器

namespace wyz//与标准库vector区别,自己定义一个命名空间,在里面写!
{
	template<class T>
	class vector
	{
	public:
        //...
         
		//迭代器
		typedef T* iterator;
		typedef const T* const_iterator;

		iterator begin()
		{
			return _start;
		}
		iterator end()
		{
			return _finish;
		}
		const_iterator cbegin()const
		{
			return _start;
		}
		const_iterator cend()const
		{
			return _finish;
		}
		
	private:
		iterator _start;
		iterator _finish;
		iterator _end_of_storage;
	};

2.2 vector反向迭代器

反向迭代器是反向遍历容器数据,它也要满足++、--、*、==、!=的功能,只不过它的++是从后往前,--是从前往后。我们很容易可以想到,反向迭代器和正向的功能差不多相同,只不过在++,--的效果相反!vector正向迭代器底层是指针,它的算法迎合基本的逻辑,++向后,--向前!我们无法直接实现让变量++指针减小,--指针增加!所以我们要用到容器适配器,底层我们可以用正向迭代器!反向的效果只要让正向反着来!--让正向++,++让正向--!这样一来我们的遍历就可以实现!也就是说,我们要将反向迭代器封装成类

下面我们直接上代码:

template<class iterator, class T>
	struct vector_reverse_iterator
	{
		typedef vector_reverse_iterator<iterator, T> Self;
	public:
        //拷贝构造
		vector_reverse_iterator(iterator s)
		{
			_it = _it;
		}
		Self& operator++()
		{
			--_it;
			return *this;
		}
		Self& operator--()
		{
			++_it;
			return *this;
		}
		T operator*()
		{
			iterator tmp = _it;
			return *(--tmp);//注意这个返回!
		}
		bool operator!=(Self s)
		{
			return _it != s._it;
		}
		bool operator==(Self s)
		{
			return _it == s._it;
		}
	private:
		iterator _it;
	};

 在来看看vector中的反向迭代器的申明与相关函数:

typedef T* iterator;
typedef const T* const_iterator;
typedef vector_reverse_iterator<iterator,T>  reverse_iterator;
typedef vector_reverse_iterator<const_iterator,const T> const_reverse_iterator;
//正向迭代器
iterator begin()
{
	return _start;
}
iterator end()
{
	return _finish;
}
const_iterator cbegin()const
{
	return _start;
}
const_iterator cend()const
{
	return _finish;
}
//反向迭代器传参,这里为了与正向对称,直接传_finish和_start
reverse_iterator rbegin()
{
	return reverse_iterator(_finish);
}
reverse_iterator rend()
{
	return reverse_iterator(_start);
}
//const反向迭代器,不能修改迭代器指向数据!
const_reverse_iterator crbegin()const
{
	return const_reverse_iterator(_finish);
}
const_reverse_iterator crend()const
{
	return const_reverse_iterator(_start);
}

💡💡现在这里主要的一个细节问题就是反向迭代器*解引用返回值!为什么要用临时变量先--后解引用返回?画一张图带你来看看!

 这里因为我的rbegin()传参为了与正向对称,没有修改迭代器初始指向!如果我让rbegin()返回的是, return reverse_iterator(_finish-1); 同样rend()返回 reverse_iterator(_start-1),就不用像上面那样先--再*了!直接*返回就可以!

2.3 模拟测试遍历vector

2.3.1 const反向迭代器效果

满足const修饰不能修改数据!


2.3.2  反向迭代器遍历

void vector_test_4()
{
	wyz::vector<int>v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	wyz::vector<int>::reverse_iterator rit = v.rbegin();
	while (rit != v.rend())
	{
		cout << *rit << ' ';
		++rit;
	}
	cout << endl;
}
void vector_test_5()
{
	wyz::vector<int>v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	wyz::vector<int>::const_reverse_iterator crit = v.crbegin();
	while (crit != v.crend())
	{
		cout << *crit << ' ';
		++crit;
	}
	cout << endl;
}
int main()
{
	cout << "vector_test_4()测试结果:";
	vector_test_4();
	cout << "vector_test_5()测试结果:";
	vector_test_5();
	return 0;
}

 


三、模拟实现list反向迭代器

3.1 list 正向迭代器

template<class T, class ref, class ptr>
struct list_iterator
{
	typedef list_node<T> node;
	typedef list_iterator<T, ref, ptr> Self;
	node* pnode;
	list_iterator(node* p)
		:pnode(p)
	{}
	ref operator*()
	{
		return pnode->data;
	}
	ptr operator->()
	{
		return &pnode->data;
	}
	//前置
	Self& operator++()
	{
		pnode = pnode->next;
		return *this;
	}
	//后置
	Self operator++(int)
	{
		Self tmp(pnode);
		pnode = pnode->next;
		return tmp;
	}
	//前置
	Self& operator--()
	{
		pnode = pnode->prev;
		return *this;
	}
	//后置
	Self operator--(int)
	{
		Self tmp(pnode);
		pnode = pnode->prev;
		return tmp;
	}

	bool operator!=(const Self& it)
	{
		return pnode != it.pnode;
	}
	bool operator==(const Self& it)
	{
		return pnode == it.pnode;
	}
};

3.2 模拟实现list反向迭代器

经过前面的vecotr反向迭代器模拟,我们知道其实反向迭代器可以用正向作容器,实现容器适配器!下面我们来实现list反向迭代器。

下面我们上代码:

template<class iterator, class ref, class ptr>
class list_reverse_iterator
{
	typedef list_reverse_iterator<iterator, ref, ptr> self;
public:
	list_reverse_iterator(iterator it)
		:_it(it)
	{}
	self& operator++()
	{
		--_it;
		return *this;
	}
	self& operator--()
	{
		++_it;
		return *this;
	}
	ref operator*()
	{
		iterator tmp = _it;
		return *(--tmp);//注意这里的先--后*
	}
	ptr operator->()
	{
		return &(operator*());//ref=T& &ref=&(T&) 即相当于T*=ptr
	}
	bool operator!=(const self& s)
	{
		return _it != s._it;
	}
	bool operator==(const self& s)
	{
		return _it == s._it;
	}
private:
	iterator _it;
};

我们再来看看list的反向迭代器申明与相关函数:

typedef list_iterator<T, T&, T*> iterator;
typedef list_iterator<T, const T&, const T*> const_iterator;
typedef list_reverse_iterator<iterator, T&, T*> reverse_iterator;
typedef list_reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;

iterator begin()
{
	//匿名对象返回!
	return iterator(head->next);
}
iterator end()
{
	return iterator(head);
}
const_iterator begin()const
{
	return const_iterator(head->next);
}
const_iterator end()const
{
	return const_iterator(head);
}

//反向迭代器
reverse_iterator rbegin()
{
	return reverse_iterator(end());
}
reverse_iterator rend()
{
	return reverse_iterator(begin());
}
//const函数重载返回const反向迭代器
const_reverse_iterator rbegin()const
{
	return const_reverse_iterator(end());
}
const_reverse_iterator rend()const
{
	return const_reverse_iterator(begin());
}

思路几乎和上面的vector一样,这里我们还要再说明一下为什么这里还是先--后*! 我们可以看到反向迭代器相关函数依然与正向相对称!我们还是画图来理解!


3.3 测试反向迭代器遍历 

3.3.1 const迭代器效果展示

3.3.2 反向迭代器遍历list

void list_test_4()
{
	const wyz::list<int> clt;
	clt.push_back(1);
	clt.push_back(2);
	clt.push_back(3);
	clt.push_back(4);
	clt.push_back(5);
	wyz::list<int>::const_reverse_iterator const_rit = clt.rbegin();
	while (const_rit != clt.rend())
	{
		//cout << (*const_rit)++ << ' ';
		cout << *const_rit << ' ';
		++const_rit;
	}
	cout << endl;
}
void list_test_5()
{
	wyz::list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);
	lt.push_back(5);
	wyz::list<int>::reverse_iterator rit = lt.rbegin();
	while (rit != lt.rend())
	{
		cout << *rit << ' ';
		++rit;
	}
	cout << endl;
}
int main()
{
	cout << "list_test_4()测试结果:";
	list_test_4();
	cout << "list_test_5()测试结果:";
	list_test_5();
	return 0;
}


 四、模拟实现vector完整版

namespcae wyz
{
template<class T>
class vector
{
public:

	//构造函数
	vector()
		:_start(nullptr)
		, _finish(nullptr)
		, _end_of_storage(nullptr)
	{}
	vector(const vector<T>& v)
		:_start(nullptr)
		, _finish(nullptr)
		, _end_of_storage(nullptr)
	{
		reserve(v.size());
		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);
	}
	vector<T>& operator=(vector<T> tmp)
	{
		swap(tmp);
		return *this;
	}
	//这里为了更加直观化,不用T* 而是重新定义一个模板Inputiterator
	template<class InputIterator>
	vector(InputIterator first, InputIterator last)
		:_start(nullptr)
		, _finish(nullptr)
		, _end_of_storage(nullptr)
	{
		reserve(last - first);
		while (first != last)
		{
			push_back(*first);
			first++;
		}
	}
	vector(int n, const T& val = T())
		:_start(nullptr)
		, _finish(nullptr)
		, _end_of_storage(nullptr)
	{
		reserve(n);
		while (n)
		{
			push_back(val);
			n--;
		}
	}

	//析构函数
	~vector()
	{
		delete[]_start;
		_start = nullptr;
		_finish = nullptr;
		_end_of_storage = nullptr;
	}

	//返回空间数据个数
	size_t size()const
	{
		return _finish - _start;
	}

	//返回空间大小
	size_t capacity()const
	{
		return _end_of_storage - _start;
	}

	//预开辟空间
	void reserve(size_t n)
	{
		if (n > capacity())
		{
			//记录数组有效个数
			size_t sz = size();
			T* tmp = new T[n];
			if (_start)
			{
				for (int i = 0;i < sz;i++)
				{
					tmp[i] = _start[i];
				}
				delete[]_start;
			}
			//更新
			_start = tmp;
			_finish = _start + sz;
			_end_of_storage = _start + n;
		}
	}

	//预指定数据个数
	void resize(size_t n, T val = T())
	{
		if (n > capacity())
		{
			//预开辟空间
			reserve(n);
			//尾插
			while (_finish < _start + n)
			{
				*_finish = val;
				_finish++;
			}
		}
		//n<capacity() 直接修改_finish位置,不需要挪动数据
		else
		{
			_finish = _start + n;
		}
	}
	template<class iterator, class T>
	struct vector_reverse_iterator
	{
		typedef vector_reverse_iterator<iterator, T> Self;
	public:
		vector_reverse_iterator(iterator it)
		{
			_it = it;
		}
		Self& operator++()
		{
			--_it;
			return *this;
		}
		Self& operator--()
		{
			++_it;
			return *this;
		}
		T operator*()
		{
			iterator tmp = _it;
			return *(--tmp);
		}
		bool operator!=(Self s)
		{
			return _it != s._it;
		}
		bool operator==(Self s)
		{
			return _it == s._it;
		}
	private:
		iterator _it;
	};
	//迭代器
	typedef T* iterator;
	typedef const T* const_iterator;
	typedef vector_reverse_iterator<iterator, T>  reverse_iterator;
	typedef vector_reverse_iterator<const_iterator, const T> const_reverse_iterator;
	iterator begin()
	{
		return _start;
	}
	iterator end()
	{
		return _finish;
	}
	const_iterator cbegin()const
	{
		return _start;
	}
	const_iterator cend()const
	{
		return _finish;
	}
	reverse_iterator rbegin()
	{
		return reverse_iterator(_finish);
	}
	reverse_iterator rend()
	{
		return reverse_iterator(_start);
	}
	const_reverse_iterator crbegin()const
	{
		return const_reverse_iterator(_finish);
	}
	const_reverse_iterator crend()const
	{
		return const_reverse_iterator(_start);
	}
	//返回数组指定位置内容
	T& operator[](size_t pos)
	{
		return _start[pos];
	}
	const T& operator[](size_t pos)const
	{
		return _start[pos];
	}
	bool empty()
	{
		return _start == _finish;
	}

	void clear()
	{
		_start = _finish;
	}
	//尾插
	void push_back(const T& x)
	{
		//判断是否需要扩容
		if (_finish == _end_of_storage)
		{
			size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
			reserve(newcapacity);
		}
		*(_finish) = x;
		_finish++;
	}

	//尾删
	void pop_back()
	{
		assert(!empty());
		_finish--;
	}

	//指定位置插入
	void insert(iterator pos, T x)
	{
		size_t n = pos - _start;
		//判断是否需要扩容
		if (_finish == _end_of_storage)
		{
			size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
			reserve(newcapacity);
			pos = _start + n;
		}
		iterator end = _finish;
		while (end >= pos)
		{
			*(end + 1) = *end;
			end--;
		}
		*(end + 1) = x;
		_finish++;
	}


	//指定位置删除
	iterator erase(iterator pos)
	{
		assert(!empty());
		iterator begin = pos;
		while (begin != _finish - 1)
		{
			*begin = *(begin + 1);
			begin++;
		}
		_finish--;
		return pos;
	}
private:
	iterator _start;
	iterator _finish;
	iterator _end_of_storage;
};
}

五、模拟实现list完整版

namespace wyz
{
	template<class T>
	struct list_node
	{
		list_node(const T& val=T())
			:prev(nullptr)
			,next(nullptr)
			,data(val)
		{}
	public:
		list_node* prev;
		list_node* next;
		T data;
	};
	template<class T,class ref,class ptr>
	struct list_iterator
	{
		typedef list_node<T> node;
		typedef list_iterator<T, ref, ptr> Self;
		node* pnode;
			list_iterator(node* p)
			:pnode(p)
		{}
		ref operator*()
		{
			return pnode->data;
		}
		ptr operator->()
		{
			return &pnode->data;
		}
		//前置
		Self& operator++()
		{
			pnode = pnode->next;
			return *this;
		}
		//后置
		Self operator++(int)
		{
			Self tmp(pnode);
			pnode = pnode->next;
			return tmp;
		}
		//前置
		Self& operator--()
		{
			pnode = pnode->prev;
			return *this;
		}
		//后置
		Self operator--(int)
		{
			Self tmp(pnode);
			pnode = pnode->prev;
			return tmp;
		}

		bool operator!=(const Self& it)
		{
			return pnode != it.pnode;
		}
		bool operator==(const Self& it)
		{
			return pnode == it.pnode;
		}
	};
	template<class iterator,class ref,class ptr>
	class list_reverse_iterator
	{
		typedef list_reverse_iterator<iterator, ref, ptr> self;
	public:
		list_reverse_iterator(iterator it)
			:_it(it)
		{}
		self& operator++()
		{
			--_it;
			return *this;
		}
		self& operator--()
		{
			++_it;
			return *this;
		}
		ref operator*()
		{
			iterator tmp = _it;
			return *(--tmp);
		}
		ptr operator->()
		{
			return &(operator*());
		}
		bool operator!=(const self& s)
		{
			return _it != s._it;
		}
		bool operator==(const self& s)
		{
			return _it == s._it;
		}
	private:
		iterator _it;
	};
	template<class T>
	class list
	{
		
	public:
		typedef list_node<T> node;
		typedef list_iterator<T,T&,T*> iterator;
		typedef list_iterator<T, const T&,const T*> const_iterator;
		typedef list_reverse_iterator<iterator, T&,T*> reverse_iterator;
		typedef list_reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;
		iterator begin()
		{
			//匿名对象返回!
			return iterator(head->next);
		}
		const_iterator begin()const
		{
			return const_iterator(head->next);
		}
		const_iterator end()const
		{
			return const_iterator(head);
		}
		iterator end()
		{
			return iterator(head);
		}
		reverse_iterator rbegin()
		{
			return reverse_iterator(end());
		}
		reverse_iterator rend()
		{
			return reverse_iterator(begin());
		}
		const_reverse_iterator rbegin()const
		{
			return const_reverse_iterator(end());
		}
		const_reverse_iterator rend()const
		{
			return const_reverse_iterator(begin());
		}
		void clear()
		{
			iterator first = begin();
			while (first != end())
			{
				first=erase(first);//!!!
			}
		}
		~list()
		{
			clear();
			delete head;
			head = nullptr;
		}
		void empty_initialize()
		{
			head = new node;
			head->next = head;
			head->prev = head;
		}
		list()
		{
			empty_initialize();
		}
		template <class InputIterator>
		list(InputIterator first, InputIterator end)
		{
			empty_initialize();
			while (first != end)
			{
				push_back(*first);
				++first;
			}
		}
		void swap(list<T>& lt)
		{
			std::swap(head, lt.head);
		}
		list(const list<T>& lt)
		{
			empty_initialize();
			list<T> tmp(lt.begin(), lt.end());
			swap(tmp);
		}
		list<T>& operator=(list<T> tmp)
		{
			swap(tmp);
			return *this;
		}
		void push_back(const T& x)const
		{
			insert(end(), x);
		}
		void push_front(const T& x)
		{
			insert(begin(), x);
		}
		void pop_front()
		{
			erase(begin());
		}
		void pop_back()
		{
			erase(--end());
		}
		void insert(iterator pos,const T& x)
		{
			node* newnode = new node(x);
			node* cur = pos.pnode;
			node* prev = cur->prev;
			prev->next = newnode;
			newnode->prev = prev;
			cur->prev = newnode;
			newnode->next = cur;
		}
		void insert(const_iterator pos, const T& x)const
		{
			node* newnode = new node(x);
			node* cur = pos.pnode;
			node* prev = cur->prev;
			prev->next = newnode;
			newnode->prev = prev;
			cur->prev = newnode;
			newnode->next = cur;
		}
		iterator erase(iterator pos)
		{
			node* cur = pos.pnode;
			node* prev = cur->prev;
			node* next = cur->next;
			prev->next = next;
			next->prev = prev;
			delete cur;
			return iterator(next);
		}
		const_iterator erase(const_iterator pos)const
		{
			node* cur = pos.pnode;
			node* prev = cur->prev;
			node* next = cur->next;
			prev->next = next;
			next->prev = prev;
			delete cur;
			return iterator(next);
		}
	private:
		node* head;//底层是一个哨兵结点
	};
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/150279.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Mybatis整合Spring的事务控制与SqlSession线程安全问题

在Spring与Mybatis框架整合中&#xff0c;主要有两个重要改动&#xff0c;分别是事务与SqlSession。mybatis-spring包中为以上两个问题提供了解决方案。 重要组件 SpringManagedTransaction &#xff08;Spring事务管理器&#xff09;SqlSessionTemplate &#xff08;SqlSess…

新年快到了,教大家用汇编语言显示Happy New Year!

新年快到了&#xff0c;教大家用汇编来显示Happy New Year! 文章目录新年快到了&#xff0c;教大家用汇编来显示Happy New Year!汇编老矣&#xff0c;尚能饭否&#xff1f;特点效率底层显示字符安装环境编写代码内存地址空间显示格式代码编译连接运行总结大家都知道&#xff0c…

使用Docker搭建主从数据库(MySQL)

很多人对主从数据库有一个误区&#xff0c;把多个MySQL搭建在同一个服务器上&#xff0c;性能提升是不是很有限&#xff1f;这个理念是错误的&#xff0c;数据库的性能瓶颈主要是在IO和CPU负载过高&#xff0c;在同一台服务器运行多个数据库&#xff0c;能带来更低的延迟&#…

Java中atomic包中的原子操作类总结

1. 原子操作类介绍 在并发编程中很容易出现并发安全的问题&#xff0c;有一个很简单的例子就是多线程更新变量 i1,比如多个线程执行 i操作&#xff0c;就有可能获取不到正确的值&#xff0c;而这个问题&#xff0c;最常用的方法是通过 Synchronized 进行控制来达到线程安全的目…

【自学Python】Python复数(complex)

Python复数(complex) Python复数(complex)教程 Python 可以支持复数&#xff0c;复数的虚部用 j 或 J 来表示。如果需要在程序中对复数进行计算&#xff0c;需要导入 Python 的 cmath 模块&#xff0c;在该模块下包含了各种支持复数运算的函数。 案例 复数 定义 Python 中…

vim光速开发,你值得拥有

文章目录vim设计哲学vim的模式什么是可视模式光标移动动作(motion)操作符(operator)操作符&#xff08;operator&#xff09;动作&#xff08;motion&#xff09;实际使用大小写转换easymotionvim-surroundTIPSideavim的使用vim设计哲学 vim被称为编辑器之神。它的成名就是因为…

Python文档阅读笔记-Turn Images into Cartoons using Python

本博文说明如何将图片转为卡通风格。 1. 导入依赖模块 在编程的第一步首先要导入依赖库&#xff0c;在这个图像转换成卡通风格的程序中需要包含3个模块&#xff0c;分别是openCV&#xff0c;numpy&#xff0c;matpoltlib。 import cv2 import numpy as np import matplotlib.…

solidity Dapp 基于merkle的选择性披露合约——我的还是我的

现在生活中&#xff0c;大家为了隐私&#xff0c;并不希望直接将个人信息给别人看&#xff0c;比如我们去住酒店时&#xff0c;需要登记姓名、身份证号信息&#xff0c;但是如果我们直接把身份证给前台人员的话&#xff0c;前台人员就可以看到我们的民族、住址等信息。那么我们…

搭建我的世界java版服务器,公网远程联机【内网穿透】

文章目录1. 搭建我的世界服务器1.1 服务器安装java环境1.2 配置服务端2. 测试局域网联机3. 公网远程联机3.1 安装cpolar内网穿透3.1.1 windows系统3.1.2 linux系统&#xff08;支持一键自动安装脚本&#xff09;3.2 创建隧道映射内网端口3.3 测试公网远程联机4. 配置固定TCP端口…

利用mybatis对数据库中的数据进行增删改查操作

写在前面&#xff1a; 本篇文章的代码都是在上一篇文章的基础上增删改&#xff0c;本篇文章并不会出现所有的代码&#xff0c;如有需求可参考上篇文章传送门 namespace中的包名要和Dao/mapper接口的包名一致&#xff1a; 假设此时我们将接口名进行修改&#xff0c;而不改变映…

windows系统,计算机cmd管理员,命令行中普通用户获取管理员权限的命令

文章目录一、第一种方式&#xff1a;搜索框搜索二、第二种方式&#xff1a;winR &#xff08;这种方式作者没有找到进入管理员的方式&#xff09;三、普通方式进入&#xff0c;通过命令授予用户权限四、通过开始右键进入cmd参考文档一、第一种方式&#xff1a;搜索框搜索 以管理…

JLINK与 SWD接口

JLINK与 SWD接口 1.使用Jlink连接 Jlink驱动&#xff1a;SEGGER - The Embedded Experts - Downloads - J-Link / J-Trace pylink文档&#xff1a;PyLink — PyLink 2.读取内存地址 3.获取内存地址的默认值 register.py 芯片配置&#xff1a; 环境搭建 1.按章Jlink 驱动…

搭建一个简单的负载均衡

前言&#xff1a; 负载均衡是互联网系统架构中必不可少的一个技术&#xff0c;通过负载均衡&#xff0c;可以将高并发的用户请求分发到多台应用服务器组成的一个服务器集群上&#xff0c;利用更多的服务器资源处理高并发下的计算压力。 早期负载均衡的实现&#xff0c;使用专…

[Linux]Linux调试器-gdb

&#x1f941;作者&#xff1a; 华丞臧. &#x1f4d5;​​​​专栏&#xff1a;【LINUX】 各位读者老爷如果觉得博主写的不错&#xff0c;请诸位多多支持(点赞收藏关注)。如果有错误的地方&#xff0c;欢迎在评论区指出。 推荐一款刷题网站 &#x1f449; LeetCode刷题网站 文…

HCIA实验(作业)

静态路由综合实验报告 实验目的 建立下图拓扑结构并满足下列要求&#xff1a; 除R5的环回地址固定以外&#xff0c;整个其他所有网段基于192.168.1.0/24进行合理的IP地址划分 R1–R4每个路由器存在两个环回接口&#xff0c;用于模拟连接PC网段&#xff0c;地址也在192.168.1.0…

使用服务网格提升应用和网络安全

当今的企业在正常进行经营的同时&#xff0c;也在不断地与潜在的黑客和不良行为者进行斗争。安全边界逐渐消失&#xff0c;攻击面不断扩大&#xff0c;新的攻击向量不断出现。再加上持续的疫情、全球冲突&#xff0c;难怪每天新闻里都有漏洞、黑客和攻击等内容。 云原生和微服…

低代码平台的七大误解(下)

接上一篇文章“低代码平台的三大误解&#xff08;上&#xff09;”&#xff0c;我们继续看看&#xff0c;人们对于低代码平台还有哪些误解。 误解四&#xff1a;低代码应用程序只能解决我的部分问题 无论您构建什么应用程序&#xff0c;它都必须是可以随着业务增长而扩展的可…

Linux应用编程---2.fork()函数

Linux应用编程—2.fork()函数 ​ fork()函数用来创建子进程&#xff0c;函数具体功能与使用方法一起看编程手册。Linux终端命令下输入&#xff1a;man fork&#xff0c;敲击回车键即可打开fork函数详情页。 2.1 fork()函数详情 图1 fork函数详情首先看SYNOPSIS: 图2 fork函数…

一分钟带你上手JS对象的基本用法

前言 相信大家对 JavaScript 中的对象都不陌生&#xff0c;而且我们几乎每天都在使用它&#xff0c;那你对对象的认识有多少呢&#xff1f;本章就带大家一起出浅入深的了解 JavaScript 中的对象。 一、什么是对象&#xff1f; 到底什么是对象呢&#xff1f;大多数人可能都会脱…

生物信息学——基础篇——一至三代测序技术

生物信息学 生物信息学——基础篇——一至三代测序技术 文章目录生物信息学一、一代测序二、二代测序三、三代测序四、总结一、一代测序 概述&#xff1a;一代测序&#xff08;又称Sanger测序&#xff09;。 原理&#xff1a;Sanger测序利用一类特殊的核昔酸&#xff0c;即dd…