C++之list(2)

news2024/11/30 14:26:56

list(2)

在这里插入图片描述

list的迭代器

在这里插入图片描述

const迭代器

根据我们之前学过的知识:

const int*p1;//修饰的是指向的内容
int *const p2;//修饰的是迭代器本身

我们写const迭代器,期望的是指向的内容不能修改。 所以更期望写上面p1的形式

const迭代器与普通迭代器的不同点在于普通迭代器既可以读也可以写,但是const修饰的迭代器只可以读

它的实现基本和普通迭代器一致:

template<class T>
	struct list_const_iterator
	{
		typedef list_node<T> Node;
		typedef list_const_iterator<T> Self;
		Node* _node;

		list_const_iterator(Node* node)
			:_node(node)
		{}

		const T& operator*()
		{
			return _node->_data;
		}

		const T* operator->()
		{
			return &_node->_data;
		}

		Self& operator++()
		{
			_node = _node->_next;
			return *this;
		}

		Self& operator--()
		{
			_node = _node->_prev;
			return *this;
		}

		Self operator++(int)
		{
			Self tmp(*this);
			_node = _node->_next;
			return tmp;
		}

		Self operator--(int)
		{
			Self tmp(*this);
			_node = _node->_prev;
			return tmp;
		}

		bool operator!=(const Self& s)
		{
			return _node != s._node;
		}
	};

不同点在于返回值的不同,因为const不希望被修改,所以要用const修饰

		const T& operator*()
		{
			return _node->_data;
		}

		const T* operator->()
		{
			return &_node->_data;
		}

在这里插入图片描述

这样子写的代码会显得有些冗余和重复,我们看stl_list.h的源代码可以发现:

在这里插入图片描述

从这里看出来,const迭代器和普通迭代器在编译器中都是用一个模板写出来两个类,模板的本质是复用

可以这样写代码:

struct list_iterator
{
	typedef list_node<T> Node;
	typedef list_iterator<T, Ref, Ptr> Self;
	Node* _node;

	list_iterator(Node* node)
		:_node(node)
	{}

	Ref operator*()//引用
	{
		return _node->_data;
	}

	Ptr operator->()//指针
	{
		return &_node->_data;
	}

	Self& operator++()
	{
		_node = _node->_next;
		return *this;
	}

	Self& operator--()
	{
		_node = _node->_prev;
		return *this;
	}

	Self operator++(int)
	{
		Self tmp(*this);
		_node = _node->_next;
		return tmp;
	}

	Self operator--(int)
	{
		Self tmp(*this);
		_node = _node->_prev;
		return tmp;
	}

	bool operator!=(const Self& s)
	{
		return _node != s._node;
	}

	bool operator==(const Self& s)
	{
		return _node == s._node;
	}
};
typedef list_iterator<T, T&, T*> iterator;
typedef list_iterator<T, const T&, const T*> const_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);
}

迭代器不需要析构,拷贝和赋值,只需要做到访问和拷贝即可,也就是浅拷贝

list的增删查改

代码如下:

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

	void push_back(const T& x)
	{
		/*Node* new_node = new Node(x);
		Node* tail = _head->_prev;

		tail->_next = new_node;
		new_node->_prev = tail;

		new_node->_next = _head;
		_head->_prev = new_node;*/

		insert(end(), x);//尾插是对插入的复用
        //因为list底层是双向循环链表,物理结构不连续,所以是在哨兵位附近的位置
	}

	void push_front(const T& x)
	{
		insert(begin(), x);
	}

	void pop_front()
	{
		erase(begin());
	}

	void pop_back()
	{
		erase(--end());
	}
//插入不会涉及到迭代器的失效问题
	iterator insert(iterator pos, const T& val)
	{
		Node* cur = pos._node;
		Node* newnode = new Node(val);
		Node* prev = cur->_prev;

		// prev newnode cur
		prev->_next = newnode;
		newnode->_prev = prev;

		newnode->_next = cur;
		cur->_prev = newnode;
		++_size;

		return iterator(newnode);
	}

	iterator erase(iterator pos)
	{
		assert(pos != end());

		Node* del = pos._node;
		Node* prev = del->_prev;
		Node* next = del->_next;

		prev->_next = next;
		next->_prev = prev;
		delete del;

		--_size;

		return iterator(next);
	}

private:
	Node* _head;
	size_t _size;

string和vector可能会出现迭代器失效的问题,但是string相比较失效的可能性更小一点,因为string会通过下标访问

析构:

~list()
		{
			clear();

			delete _head;
			_head = nullptr;
		}

		
//clear只清理数据,不清理空间
		void clear()
		{
			auto it = begin();
			while (it != end())
			{
                //避免迭代器失效
				it = erase(it);
			}
		}

拷贝:

list()
{
	empty_init();
}

// lt2(lt1)
list(const list<T>& lt)
{
	empty_init();
//这里是深拷贝,引用,不是引用的话,又会形成拷贝
	for (auto& e : lt)
	{
		push_back(e);
	}
}

赋值:

// lt2 = lt3
//list& operator=(list lt)
list<T>& operator=(list<T> lt)
{
	swap(lt);
	return *this;
}
void swap(list<T>& tmp)
{
	std::swap(_head, tmp._head);
	std::swap(_size, tmp._size);
}

交换

template <class T>
    //这个是调用库里面的
void swap(T& a, T& b)
{
	T c(a); a = b; b = c;
}
//这个是针对list提炼出的一个模板
template <class T>
void swap(list<T>& a, list<T>& b)
{
	a.swap(b);
}

模板的话,编译器会更加优先匹配适配程度更高的模板,所以我们这里会调用下面的模板,效率会更加高效

模拟实现list的代码如下:

List.h

#pragma once
#include<assert.h>

namespace soobin
{
	// 惯例
	// 全部都是公有,一般用struct
	template<class T>
	struct list_node
	{
		T _data;
		list_node<T>* _next;
		list_node<T>* _prev;

		list_node(const T& x = T())
			:_data(x)
			, _next(nullptr)
			, _prev(nullptr)
		{}
	};

	// typedef list_iterator<T, T&, T*> iterator;
	// typedef list_iterator<T, const T&, const T*> const_iterator;

	template<class T, class Ref, class Ptr>
	struct list_iterator
	{
		typedef list_node<T> Node;
		typedef list_iterator<T, Ref, Ptr> Self;
		Node* _node;

		list_iterator(Node* node)
			:_node(node)
		{}

		Ref operator*()
		{
			return _node->_data;
		}

		Ptr operator->()
		{
			return &_node->_data;
		}

		Self& operator++()
		{
			_node = _node->_next;
			return *this;
		}

		Self& operator--()
		{
			_node = _node->_prev;
			return *this;
		}

		Self operator++(int)
		{
			Self tmp(*this);
			_node = _node->_next;
			return tmp;
		}

		Self operator--(int)
		{
			Self tmp(*this);
			_node = _node->_prev;
			return tmp;
		}

		bool operator!=(const Self& s)
		{
			return _node != s._node;
		}

		bool operator==(const Self& s)
		{
			return _node == s._node;
		}
	};

	/*template<class T>
	struct list_const_iterator
	{
		typedef list_node<T> Node;
		typedef list_const_iterator<T> Self;
		Node* _node;

		list_const_iterator(Node* node)
			:_node(node)
		{}

		const T& operator*()
		{
			return _node->_data;
		}

		const T* operator->()
		{
			return &_node->_data;
		}

		Self& operator++()
		{
			_node = _node->_next;
			return *this;
		}

		Self& operator--()
		{
			_node = _node->_prev;
			return *this;
		}

		Self operator++(int)
		{
			Self tmp(*this);
			_node = _node->_next;
			return tmp;
		}

		Self operator--(int)
		{
			Self tmp(*this);
			_node = _node->_prev;
			return tmp;
		}

		bool operator!=(const Self& s)
		{
			return _node != s._node;
		}
	};*/

	template<class T>
	class list
	{
		typedef list_node<T> Node;
	public:
		/*typedef list_iterator<T> iterator;
		typedef list_const_iterator<T> const_iterator;*/

		typedef list_iterator<T, T&, T*> iterator;
		typedef list_iterator<T, const T&, const T*> const_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);
		}

		void empty_init()
		{
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head;
			_size = 0;//有效个数大小,增加这个成员变量使其更高效
		}

		list()
		{
			empty_init();
		}

		// lt2(lt1)
		list(const list<T>& lt)
		{
			empty_init();

			for (auto& e : lt)
			{
				push_back(e);
			}
		}

		// lt2 = lt3
		//list& operator=(list lt)
		list<T>& operator=(list<T> lt)
		{
			swap(lt);
			return *this;
		}

		~list()
		{
			clear();

			delete _head;
			_head = nullptr;
		}

		void swap(list<T>& tmp)
		{
			std::swap(_head, tmp._head);
			std::swap(_size, tmp._size);
		}

		void clear()
		{
			auto it = begin();
			while (it != end())
			{
				it = erase(it);
			}
		}

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

		void push_back(const T& x)
		{
			/*Node* new_node = new Node(x);
			Node* tail = _head->_prev;

			tail->_next = new_node;
			new_node->_prev = tail;

			new_node->_next = _head;
			_head->_prev = new_node;*/

			insert(end(), x);
		}

		void push_front(const T& x)
		{
			insert(begin(), x);
		}

		void pop_front()
		{
			erase(begin());
		}

		void pop_back()
		{
			erase(--end());
		}

		iterator insert(iterator pos, const T& val)
		{
			Node* cur = pos._node;
			Node* newnode = new Node(val);
			Node* prev = cur->_prev;

			// prev newnode cur
			prev->_next = newnode;
			newnode->_prev = prev;

			newnode->_next = cur;
			cur->_prev = newnode;
			++_size;//插入高效

			return iterator(newnode);
		}

		iterator erase(iterator pos)
		{
			assert(pos != end());

			Node* del = pos._node;
			Node* prev = del->_prev;
			Node* next = del->_next;

			prev->_next = next;
			next->_prev = prev;
			delete del;

			--_size;//删除元素高效

			return iterator(next);
		}

	private:
		Node* _head;
		size_t _size;
	};

	template <class T>
	void swap(T& a, T& b)
	{
		T c(a); a = b; b = c;
	}

	template <class T>
	void swap(list<T>& a, list<T>& b)
	{
		a.swap(b);
	}
}

Test.cpp

#include<iostream>
#include<algorithm>
#include<list>
#include<vector>
using namespace std;

//int main()
//{
//	list<int> lt1;
//	lt1.push_back(1);
//	lt1.push_back(1);
//	lt1.push_back(1);
//	lt1.push_back(1);
//	lt1.emplace_back(10);
//
//	list<int> lt2 = {1,2,3,4,5};
//
//	list<int>::iterator it1 = lt1.begin();
//	while (it1 != lt1.end())
//	{
//		cout << *it1 << " ";
//		++it1;
//	}
//	cout << endl;
//
//	for (auto e : lt2)
//	{
//		cout << e << " ";
//	}
//	cout << endl;
//
//	return 0;
//}

class Pos
{
public:
	int _row;
	int _col;

	Pos(int row = 0, int col = 0)
		:_row(row)
		, _col(col)
	{
		cout << "Pos(int row, int col)" << endl;
	}

	Pos(const Pos& p)
		:_row(p._row)
		, _col(p._col)
	{
		cout << "Pos(const Pos& p)" << endl;
	}
};

//int main()
//{
//	list<Pos> lt;
//
//	// 构造+拷贝构造
//	Pos p1(1, 1);
//	lt.push_back(p1);
//	lt.push_back(Pos(2, 2));
//	lt.push_back({3,3});
//
//	lt.emplace_back(p1);
//	lt.emplace_back(Pos(2, 2));
//	//lt.emplace_back({ 3,3 });
//
//	// 直接构造
//	lt.emplace_back(3, 3);
//
//	return 0;
//}

//int main()
//{
//	list<int> lt1 = { 1,2,3,4,5 };
//
//	for (auto e : lt1)
//	{
//		cout << e << " ";
//	}
//	cout << endl;
//
//	int x;
//	cin >> x;
//	auto it = find(lt1.begin(), lt1.end(), x);
//	if (it != lt1.end())
//	{
//		lt1.erase(it);
//	}
//
//	for (auto e : lt1)
//	{
//		cout << e << " ";
//	}
//	cout << endl;
//
//	return 0;
//}

//int main()
//{
//	list<int> lt1 = { 1,2,3,4,5 };
//	// LRU
//	int x;
//	
//	while (cin >> x)
//	{
//		auto pos = find(lt1.begin(), lt1.end(), x);
//		if (pos != lt1.end())
//		{
//			lt1.splice(lt1.begin(), lt1, pos);
//		}
//
//		for (auto e : lt1)
//		{
//			cout << e << " ";
//		}
//		cout << endl;
//	}
//
//	cout << "xxxxxxxxxxxxxxxxxxxxxx" << endl;
//
//	return 0;
//}

//int main()
//{
//	list<int> lt1 = { 1,20,3,-4,5 };
//	for (auto e : lt1)
//	{
//		cout << e << " ";
//	}
//	cout << endl;
//
//	// <
//	//lt1.sort();
//	// >
//	/*greater<int> gt;
//	lt1.sort(gt);*/
//	lt1.sort(greater<int>());
//
//	// 不能用
//	//sort(lt1.begin(), lt1.end(), greater<int>());
//	for (auto e : lt1)
//	{
//		cout << e << " ";
//	}
//	cout << endl;
//
//	vector<int> v1 = { 1,20,3,-4,5 };
//	for (auto e : v1)
//	{
//		cout << e << " ";
//	}
//	cout << endl;
//
//	//sort(v1.begin(), v1.end());
//	sort(v1.begin(), v1.end(), greater<int>());
//	for (auto e : v1)
//	{
//		cout << e << " ";
//	}
//	cout << endl;
//
//
//	return 0;
//}

void test_op1()
{
	srand(time(0));
	const int N = 1000000;

	list<int> lt1;
	list<int> lt2;

	vector<int> v;

	for (int i = 0; i < N; ++i)
	{
		auto e = rand() + i;
		lt1.push_back(e);
		v.push_back(e);
	}

	int begin1 = clock();
	// 排序
	sort(v.begin(), v.end());
	int end1 = clock();

	int begin2 = clock();
	lt1.sort();
	int end2 = clock();

	printf("vector sort:%d\n", end1 - begin1);
	printf("list sort:%d\n", end2 - begin2);
}

void test_op2()
{
	srand(time(0));
	const int N = 1000000;

	list<int> lt1;
	list<int> lt2;

	for (int i = 0; i < N; ++i)
	{
		auto e = rand();
		lt1.push_back(e);
		lt2.push_back(e);
	}

	int begin1 = clock();
	// 拷贝vector

	vector<int> v(lt2.begin(), lt2.end());
	// 排序
	sort(v.begin(), v.end());

	// 拷贝回lt2
	lt2.assign(v.begin(), v.end());

	int end1 = clock();

	int begin2 = clock();
	lt1.sort();
	int end2 = clock();

	printf("list copy vector sort copy list sort:%d\n", end1 - begin1);
	printf("list sort:%d\n", end2 - begin2);
}
//
//int main()
//{
//	test_op1();
//	test_op2();
//
//	return 0;
//}

#include"List.h"

//int main()
//{
//	bit::list<int> lt1;
//	lt1.push_back(1);
//	lt1.push_back(1);
//	lt1.push_back(1);
//	lt1.push_back(1);
//
//	soobin::list<int>::iterator it1 = lt1.begin();
//	while (it1 != lt1.end())
//	{
//		*it1 = 2;
//
//		cout << *it1 << " ";
//		++it1;
//	}
//	cout << endl;
//
//	for (auto e : lt1)
//	{
//		cout << e << " ";
//	}
//	cout << endl;
//
//	soobin::list<Pos> lt2;
//	Pos p1(1, 1);
//	lt2.push_back(p1);
//	lt2.push_back(Pos(2, 2));
//	lt2.push_back({3,3});
//
//	soobin::list<Pos>::iterator it2 = lt2.begin();
//	while (it2 != lt2.end())
//	{
//		//cout << (*it2)._row << ":" << (*it2)._col << endl;
//		// 为了可读性,特殊处理,省略了一个->
//		cout << it2->_row << ":" << it2->_col << endl;
//		cout << it2.operator->()->_row << ":" << it2.operator->()->_col << endl;
//
//		++it2;
//	}
//	cout << endl;
//}

//int main()
//{
//	const soonbin::list<int> lt1(10, 1);
//
//	// const int* p1  
//	// int* const p2
//	soobin::list<int>::const_iterator it1 = lt1.begin();
//	while (it1 != lt1.end())
//	{
//		//*it1 = 2;
//		cout << *it1 << " ";
//		++it1;
//	}
//	cout << endl;
//
//	for (auto e : lt1)
//	{
//		cout << e << " ";
//	}
//	cout << endl;
//
//	return 0;
//}

//int main()
//{
//	soobin::list<int> lt1;
//	lt1.push_back(1);
//	lt1.push_back(2);
//	lt1.push_back(3);
//	lt1.push_back(4);
//	lt1.push_front(0);
//	lt1.push_front(-1);
//
//	soobin::list<int>::iterator it1 = lt1.begin();
//	while (it1 != lt1.end())
//	{
//		cout << *it1 << " ";
//		++it1;
//	}
//	cout << endl;
//
//	lt1.pop_front();
//	lt1.pop_back();
//
//	for (auto e : lt1)
//	{
//		cout << e << " ";
//	}
//	cout << endl;
//
//	soobin::list<int> lt2(lt1);
//	for (auto e : lt2)
//	{
//		cout << e << " ";
//	}
//	cout << endl;
//
//	soobin::list<int> lt3(10, 1);
//	lt2 = lt3;
//	for (auto e : lt2)
//	{
//		cout << e << " ";
//	}
//	cout << endl;
//}

int main()
{
	bit::list<int> lt1;
	lt1.push_back(1);
	lt1.push_back(2);
	lt1.push_back(3);
	lt1.push_back(4);
	lt1.push_front(0);
	lt1.push_front(-1);

	soobin::list<int> lt2(10, 1);
	//lt1.swap(lt2);

	int i = 1, j = 2;
	soobin::swap(i, j);
	soobin::swap(lt1, lt2);

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

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

	return 0;
}

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

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

相关文章

03 设计模式-创造型模式-单例模式

单例模式&#xff08;Singleton Pattern&#xff09;是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式。 这种模式涉及到一个单一的类&#xff0c;该类负责创建自己的对象&#xff0c;同时确保只有单个对象被创建…

C语言复习第4章 数组

目录 一、一维数组的创建和初始化1.1数组的创建1.2 变长数组1.3 数组的初始化1.4 全局数组默认初始化为01.5 区分两种字符数组1.6 用sizeof计算数组元素个数1.7 如何访问数组元素1.8 一维数组在内存中的存储(连续存储)1.9 访问数组元素的另一种方式:指针变量1.10 数组越界是运行…

【AI绘画】Midjourney进阶:引导线构图详解

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AI绘画 | Midjourney 文章目录 &#x1f4af;前言&#x1f4af;什么是构图为什么Midjourney要使用构图 &#x1f4af;引导线构图特点使用场景提示词书写技巧测试 &#x1f4af;小结 &#x1f4af;前言 【AI绘画】Midjourney进阶&a…

AnaTraf | TCP重传的工作原理与优化方法

目录 什么是TCP重传&#xff1f; TCP重传的常见触发原因 TCP重传对网络性能的影响 1. 高延迟与重传 2. 吞吐量的下降 如何优化和减少TCP重传 1. 优化网络设备配置 2. 优化网络链路 3. 网络带宽的合理规划 4. 部署CDN和缓存策略 结语 AnaTraf 网络性能监控系统NPM | …

网络最快的速度光速,因此‘‘光网络‘‘由此产生

世界上有一种最快的速度又是光,以前传统以太网络规划满足不了现在的需求。 一 有线网规划 二 无线网规划

如何用pyhton修改1000+图片的名字?

import os oldpath input("请输入文件路径&#xff08;在windows中复制那个图片文件夹的路径就可以):") #注意window系统中的路径用这个‘\分割&#xff0c;但是编程语言中一般都是正斜杠也就是’/‘ #这里写一个代码&#xff0c;将 \ > / path "" fo…

嵌入式职业规划

嵌入式职业规划 在嵌入式的软件开发中&#xff0c;可以分为&#xff1a; 嵌入式MCU软件开发工程师&#xff1b; 嵌入式Linux底层&#xff08;BSP&#xff09;软件开发工程师&#xff1b; 嵌入式Linux应用开发工程师&#xff1b; 嵌入式FPGA算法开发工程师 对于前两个阶段 …

H.266与H.265、AV1、H.264对比

好多开发者希望搞清楚H.266&#xff08;Versatile Video Coding&#xff0c;VVC&#xff09;、H.265&#xff08;High Efficiency Video Coding&#xff0c;HEVC&#xff09;、AV1、H.264&#xff08;Advanced Video Coding&#xff09;四者区别&#xff0c;本文从压缩效率、画…

代码随想录算法训练营第三十八天 | 62. 不同路径、63. 不同路径 II、343. 整数拆分、96.不同的二叉搜索树(343、96以后学)

1. 题目&#xff1a; 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有多少条不同的路…

提高EDM广告发送率和到达率_实用技巧揭秘

EDM广告提高发送率和到达率策略包括优化邮件服务器设置、制定邮件内容及设计策略、持续监测与测试。ZohoCampaigns通过可靠ESP、SPF和DKIM验证、维护IP声誉确保高发送率和到达率。 一、了解EDM的发送率和到达率概念 在深入研究提升策略之前&#xff0c;首先我们需要明确两个专…

2-126基于matlab希尔伯特黄变换(HHT)的图像三维重建

基于matlab希尔伯特黄变换&#xff08;HHT&#xff09;的图像三维重建&#xff0c;利用希尔伯特黄变换&#xff08;HHT&#xff09;的条纹图相位信息提取算法&#xff0c;对输入图片的变形条纹图相位信息进行提取&#xff0c;实现三维重建。程序已调通&#xff0c;可直接运行。…

Axure重要元件三——中继器时间排序

亲爱的小伙伴&#xff0c;在您浏览之前&#xff0c;烦请关注一下&#xff0c;在此深表感谢&#xff01; 本节课&#xff1a;中继器数据时间排序 课程内容&#xff1a;数据的升序、降序、重置排序 应用场景&#xff1a;表单数据的排序 案例展示&#xff1a; 步骤一&#xff…

【数据分享】1901-2023年我国省市县三级逐月最低气温(免费获取/Shp/Excel格式)

之前我们分享过1901-2023年1km分辨率逐月最低气温栅格数据&#xff08;可查看之前的文章获悉详情&#xff09;&#xff0c;该数据来源于国家青藏高原科学数据中心&#xff0c;很多小伙伴拿到数据后反馈栅格数据不太方便使用&#xff0c;问我们能不能把数据处理为更方便使用的Sh…

0基础学java之Day09(下午完整版)

六、数组 概念&#xff1a; 1.数组是引用数据类型 2.数组中的数据叫做元素 3.元素都有标号叫做索引/下标 4.下标从0开始 5.数组一旦初始化成功&#xff0c;长度不可变&#xff08;意味着数组没有添加和删除&#xff09; 6.数组中的元素在内存中是挨在一起的 声明&#xff1a; 数…

CTF(四)

导言&#xff1a; 本文主要讲述在CTF竞赛中&#xff0c;web类题目file_include。 靶场链接&#xff1a;攻防世界 (xctf.org.cn) 一&#xff0c;观察页面。 可以看到一段php代码。从则段代码中我们可以知道&#xff1a; 1&#xff0c;使用include引入check.php文件&#xff…

Excel制作工资表

需要用到的函数 函数要求如下&#xff1a; IFERROR 功能&#xff1a;处理公式中的错误&#xff0c;避免显示错误值。当公式产生错误时&#xff0c;使用自定义的值或表达式代替错误信息。 IFERROR(值, 错误值)SUM 功能&#xff1a;求和&#xff0c;计算一系列数字的总和。 语…

SSD |(七)FTL详解(中)

文章目录 &#x1f4da;垃圾回收&#x1f407;垃圾回收原理&#x1f407;写放大&#x1f407;垃圾回收实现&#x1f407;垃圾回收时机 &#x1f4da;解除映射关系&#x1f4da;磨损均衡 &#x1f4da;垃圾回收 &#x1f407;垃圾回收原理 ✋设定一个迷你SSD空间&#xff1a; 假…

Windows 和 Ubuntu通讯的网络设置

如果你是一个嵌入式工程师&#xff0c;因为工作需要&#xff0c;在linux下进行开发&#xff0c;一定会遇见配网问题。这篇文章解决Windows 和虚拟机Ubuntu通讯的网络设置的问题。 Windows的网络配置&#xff1a; 在配置网络前&#xff0c;先了解一下windows和ubuntu的网络构成…

CTFHUB技能树之SQL——过滤空格

开启靶场&#xff0c;打开链接&#xff1a; 既然是过滤空格&#xff0c;绕过空格的方法&#xff1a; 用/**/或%0a替代空格 &#xff08;1&#xff09;判断注入点 1 and 11# 会显示hacker 1/**/and/**/11# 有回显 1/**/and/**/12# 无回显&#xff0c;说明是整数型注入 &#…

嵌入式C++中内存分配基本实现方法

大家好,今天主要给大家分享一下,如何使用计算机中的内存空间进行分配,观察具体现象。 第一:C语言动态空间分配方式 第二:C++中动态内存分配方法 new 可以自动计算数据类型的大小 与 类型的转换 malloc 只能手动进行。 2.new 可以在分配空间的时候初始化 malloc 不行。 第三…