【031】C++类和对象之运算符重载详解和代码实践(最全讲解)

news2024/11/17 0:06:51

C++类和对象之运算符重载详解

  • 引言
  • 一、运算符重载的基本概念
    • 1.1、可重载的运算符
    • 1.2、不可重载的运算符
  • 二、重载 << 运算符(全局函数实现)
  • 三、重载 >> 运算符(全局函数实现)
  • 四、重载 + 运算符
    • 4.1、全局函数实现
    • 4.2、成员函数实现(推荐)
  • 五、重载 == 运算符(成员函数实现)
  • 六、重载 ++ / -- 运算符
    • 6.1、重载后置++
    • 6.2、前后置++
    • 6.2、前后置 -- 和后置 --
  • 七、案例:设计一个MyString类
  • 八、仿函数:重载函数调用运算符 ()
  • 九、智能指针(指针运算符 *、-> 重载)
  • 十、不要重载 && 和 || 运算符
  • 总结

引言


💡 作者简介:专注于C/C++高性能程序设计和开发,理论与代码实践结合,让世界没有难学的技术。包括C/C++、Linux、MySQL、Redis、TCP/IP、协程、网络编程等。
👉
🎖️ CSDN实力新星,社区专家博主
👉
🔔 专栏介绍:从零到c++精通的学习之路。内容包括C++基础编程、中级编程、高级编程;掌握各个知识点。
👉
🔔 专栏地址:C++从零开始到精通
👉
🔔 博客主页:https://blog.csdn.net/Long_xu


🔔 上一篇:【030】C++类和对象之友元(friend)详解

一、运算符重载的基本概念

运算符重载是C++中一种特殊的语言特性,它允许程序员重新定义现有的运算符,使其适用于自定义类型或类对象。通过运算符重载,可以为自己创建的数据类型定义新的操作行为,增加代码可读性和易用性。

运算符重载的基本概念包括:

  1. 运算符:C++中已经定义好了多个运算符,如加号、减号、乘号、除号等。
  2. 操作数:参与运算的数据对象。
  3. 重载函数:为了实现对某个特定类型的操作而定义的函数。
  4. 成员函数和非成员函数:两种实现方式。成员函数通常用于对类对象进行操作,而非成员函数则通常用于不涉及类对象的情况下进行计算。

语法:定义重载的运算符就像定义函数,只是该函数的名字是operator@,这里的@代表被重载的运算符。例如,可以通过重载"+"运算符来实现两个自定义类型对象相加,并返回一个新对象作为结果。在这种情况下,需要编写一个名为operator+()的重载函数,并在其中定义相应的操作行为。

思路:
(1)弄清楚运算符的运算对象的个数;个数决定了重载函数的参数个数。
(2)识别运算符左边的运算对象是类的对象还是其他:

  • 类的对象:推荐使用成员函数实现,可以少一个参数;不推荐全局函数实现。
  • 其他:只能全局函数实现。

1.1、可重载的运算符

+-*/%^&|
~!=<>+=-=*=
/=^=&=|=<<>>>>=<<=
==!=<=>=&&||++
->*->[]()newdeletenew[]和delete[]

尽量不要重载&&和||,因为无法完成它们的短路特性。

1.2、不可重载的运算符

.::.*?:sizeof

二、重载 << 运算符(全局函数实现)

使用全局函数重载运算符必须将全局函数设置为友元。

#include <iostream>
#include <string>
using namespace std;

class MyPerson {
	friend ostream& operator<<(ostream &out, MyPerson &ob);
private:
	int num;
	string name;
	float score;
public:
	MyPerson()
	{
		num = 0;
		name = "Lion";
		score = 0.0f;
	}
	MyPerson(int num, string name, float score) :num(num), name(name), score(score)
	{

	}
};
// 全局函数
ostream& operator<<(ostream &out, MyPerson &ob)
{
	out << ob.name << " " << ob.num << " " << ob.score << endl;
	return out;
}

int main()
{
	MyPerson person;
	MyPerson p2(100, "Long", 100.0f);
	cout << person << endl;// 相当于operator<<(cout, person);
	cout << person << p2 << endl;
	return 0;
}

三、重载 >> 运算符(全局函数实现)

#include <iostream>
#include <string>
using namespace std;

class MyPerson {
	friend ostream& operator<<(ostream &out, MyPerson &ob);
	friend istream& operator>>(istream &in, MyPerson &ob);
private:
	int num;
	string name;
	float score;
public:
	MyPerson()
	{
		num = 0;
		name = "Lion";
		score = 0.0f;
	}
	MyPerson(int num, string name, float score) :num(num), name(name), score(score)
	{

	}
};
// 全局函数
ostream& operator<<(ostream &out, MyPerson &ob)
{
	out << ob.name << " " << ob.num << " " << ob.score << endl;
	return out;
}

istream& operator>>(istream &in, MyPerson &ob)
{
	in >> ob.name >> ob.num >> ob.score;
	return in;
}

int main()
{
	MyPerson person;
	cin >> person;
	MyPerson p2(100, "Long", 100.0f);
	cout << person << endl;// 相当于operator<<(cout, person);
	cout << person << p2 << endl;
	return 0;
}

四、重载 + 运算符

4.1、全局函数实现

#include <iostream>
#include <string>
using namespace std;

class MyPerson {
	friend ostream& operator<<(ostream &out, MyPerson ob);
	friend MyPerson operator+(MyPerson  &ob1, MyPerson &ob2);
private:
	int num;
	string name;
	float score;
public:
	MyPerson()
	{
		num = 0;
		name = "Lion";
		score = 0.0f;
	}
	MyPerson(int num, string name, float score) :num(num), name(name), score(score)
	{

	}
};
// 全局函数
ostream& operator<<(ostream &out, MyPerson ob)
{
	out << ob.name << " " << ob.num << " " << ob.score << endl;
	return out;
}

MyPerson operator+(MyPerson  &ob1,MyPerson &ob2)
{
	MyPerson tmp;
	tmp.name = ob1.name + ob2.name;
	tmp.num = ob1.num + ob2.num;
	tmp.score = ob1.score + ob2.score;
	return tmp;
}

int main()
{
	MyPerson person(1,"Lion",98.9f);
	MyPerson p2(100, "Long", 100.0f);
	cout << person + p2 << endl;// 相当于operator<<(cout, person);
	return 0;
}

4.2、成员函数实现(推荐)

#include <iostream>
#include <string>
using namespace std;

class MyPerson {
	friend ostream& operator<<(ostream &out, MyPerson ob);
private:
	int num;
	string name;
	float score;
public:
	MyPerson()
	{
		num = 0;
		name = "Lion";
		score = 0.0f;
	}
	MyPerson(int num, string name, float score) :num(num), name(name), score(score)
	{

	}
	// 成员函数实现 重载 + 运算符
	MyPerson operator+(MyPerson &ob2)
	{
		MyPerson tmp;
		tmp.name = name + ob2.name;
		tmp.num = num + ob2.num;
		tmp.score = score + ob2.score;
		return tmp;
	}
	
};
// 全局函数
ostream& operator<<(ostream &out, MyPerson ob)
{
	out << ob.name << " " << ob.num << " " << ob.score << endl;
	return out;
}

/*
MyPerson operator+(MyPerson  &ob1,MyPerson &ob2)
{
	MyPerson tmp;
	tmp.name = ob1.name + ob2.name;
	tmp.num = ob1.num + ob2.num;
	tmp.score = ob1.score + ob2.score;
	return tmp;
}
*/
int main()
{
	MyPerson person(1,"Lion",98.9f);
	MyPerson p2(100, "Long", 100.0f);
	cout << person + p2 << endl;// 相当于person.operator+(p2);
	return 0;
}

五、重载 == 运算符(成员函数实现)

#include <iostream>
#include <string>
using namespace std;

class MyPerson {
	friend ostream& operator<<(ostream &out, MyPerson ob);
private:
	int num;
	string name;
	float score;
public:
	MyPerson()
	{
		num = 0;
		name = "Lion";
		score = 0.0f;
	}
	MyPerson(int num, string name, float score) :num(num), name(name), score(score)
	{

	}
	// 成员函数实现重载 + 运算符
	MyPerson operator+(MyPerson &ob2)
	{
		MyPerson tmp;
		tmp.name = name + ob2.name;
		tmp.num = num + ob2.num;
		tmp.score = score + ob2.score;
		return tmp;
	}
	// 成员函数实现 重载 == 运算符
	bool operator==(MyPerson &ob2)
	{
		if (name == ob2.name && num == ob2.num && score == ob2.score)
			return true;
		return false;
	}
};
// 全局函数
ostream& operator<<(ostream &out, MyPerson ob)
{
	out << ob.name << " " << ob.num << " " << ob.score << endl;
	return out;
}

/*
MyPerson operator+(MyPerson  &ob1,MyPerson &ob2)
{
	MyPerson tmp;
	tmp.name = ob1.name + ob2.name;
	tmp.num = ob1.num + ob2.num;
	tmp.score = ob1.score + ob2.score;
	return tmp;
}
*/
int main()
{
	MyPerson person(1,"Lion",98.9f);
	MyPerson p2(100, "Long", 100.0f);
	
	if (person == p2)
	{
		cout << "相等" << endl;
	}
	else
		cout << "不相等" << endl;

	MyPerson p3(1, "Lion", 98.9f);
	if (person == p3)
	{
		cout << "相等" << endl;
	}
	else
		cout << "不相等" << endl;
	return 0;
}

六、重载 ++ / – 运算符

重载的 ++ 和 – 运算符会复杂一些,因为希望能根据它们出现在所作用对象的前面还是后面来调用不同的函数。解决办法很简单:利用函数重载的占位符机制。例如,当编译器看到++a(前置++)时调用operator++(a);当编译器看到a++(后置++)时调用operator++(a,int)。

  • 前置++,调用operator++(a)。
  • 后置++,调用operator++(a,int)。
  • 前置–,调用operator–(a)。
  • 后置–,调用operator–(a,int)。

6.1、重载后置++

类名称 operator++(int)
{
	// 先保存旧的值
	// 自增
	// return 返回旧的值
}

代码示例:

#include <iostream>
#include <string>
using namespace std;

class MyPerson {
	friend ostream& operator<<(ostream &out, MyPerson ob);
private:
	int num;
	string name;
	float score;
public:
	MyPerson()
	{
		num = 0;
		name = "Lion";
		score = 0.0f;
	}
	MyPerson(int num, string name, float score) :num(num), name(name), score(score)
	{

	}
	// 成员函数实现重载 + 运算符
	MyPerson operator+(MyPerson &ob2)
	{
		MyPerson tmp;
		tmp.name = name + ob2.name;
		tmp.num = num + ob2.num;
		tmp.score = score + ob2.score;
		return tmp;
	}
	// 成员函数实现 重载 == 运算符
	bool operator==(MyPerson &ob2)
	{
		if (name == ob2.name && num == ob2.num && score == ob2.score)
			return true;
		return false;
	}
	// 成员函数实现 重载 后置++ 运算符
	MyPerson operator++(int)
	{
		// 保存旧值
		MyPerson old = *this;
		// 自增
		this->name = this->name + this->name;
		this->num++;
		this->score++;
		// 返回旧值
		return old;

	}
};
// 全局函数
ostream& operator<<(ostream &out, MyPerson ob)
{
	out << ob.name << " " << ob.num << " " << ob.score << endl;
	return out;
}

/*
MyPerson operator+(MyPerson  &ob1,MyPerson &ob2)
{
	MyPerson tmp;
	tmp.name = ob1.name + ob2.name;
	tmp.num = ob1.num + ob2.num;
	tmp.score = ob1.score + ob2.score;
	return tmp;
}
*/
int main()
{
	MyPerson person(1,"Lion",98.9f);
	MyPerson p2;

	p2 = person++;
	cout << p2 << endl;
	cout << person << endl;
	return 0;
}

6.2、前后置++

类名称 operator++(int)
{
	// 自增
	// return 返回当前新的值
}

示例:

#include <iostream>
#include <string>
using namespace std;

class MyPerson {
	friend ostream& operator<<(ostream &out, MyPerson ob);
private:
	int num;
	string name;
	float score;
public:
	MyPerson()
	{
		num = 0;
		name = "Lion";
		score = 0.0f;
	}
	MyPerson(int num, string name, float score) :num(num), name(name), score(score)
	{

	}
	// 成员函数实现重载 + 运算符
	MyPerson operator+(MyPerson &ob2)
	{
		MyPerson tmp;
		tmp.name = name + ob2.name;
		tmp.num = num + ob2.num;
		tmp.score = score + ob2.score;
		return tmp;
	}
	// 成员函数实现 重载 == 运算符
	bool operator==(MyPerson &ob2)
	{
		if (name == ob2.name && num == ob2.num && score == ob2.score)
			return true;
		return false;
	}
	// 成员函数实现 重载 后置++ 运算符
	MyPerson operator++(int)
	{
		// 保存旧值
		MyPerson old = *this;
		// 自增
		this->name = this->name + this->name;
		this->num++;
		this->score++;
		// 返回旧值
		return old;

	}
	// 成员函数实现 重载 前置++ 运算符
	MyPerson operator++()
	{
		// 自增
		this->name = this->name + this->name;
		this->num++;
		this->score++;
		// 返回新值
		return *this;
	}
};
// 全局函数
ostream& operator<<(ostream &out, MyPerson ob)
{
	out << ob.name << " " << ob.num << " " << ob.score << endl;
	return out;
}

/*
MyPerson operator+(MyPerson  &ob1,MyPerson &ob2)
{
	MyPerson tmp;
	tmp.name = ob1.name + ob2.name;
	tmp.num = ob1.num + ob2.num;
	tmp.score = ob1.score + ob2.score;
	return tmp;
}
*/
int main()
{
	MyPerson person(1,"Lion",98.9f);
	MyPerson p2;

	p2 = ++person;
	cout << p2 << endl;
	cout << person << endl;
	return 0;
}

输出:

LionLion 2 99.9

LionLion 2 99.9

6.2、前后置 – 和后置 –

重载–运算符的代码和 ++的类似,直接参考上述的重载 ++运算符代码。

七、案例:设计一个MyString类

此案例会重载以下的运算符:[]、<<、>>、+、=、>、<、==。

#include <iostream>
#include <string.h>
using namespace std;

class MyString {
	//全局函数重载 << 运算符
	friend ostream& operator<<(ostream &out, MyString str);
	//全局函数重载 >> 运算符
	friend istream& operator>>(istream &in, MyString &ob);
private:
	char *str;//保存字符串
	int size;
public:
	MyString();
	MyString(const char *str);
	MyString(const MyString &ob);
	~MyString();
	int getSize();
	// 成员函数重载 [] 运算符
	char& operator[](int pos);
	// 成员函数重载 + 运算符
	MyString operator+(MyString &ob);
	MyString operator+(const char *str);
	// 成员函数重载 = 运算符
	MyString& operator=(MyString &ob);
	MyString& operator=(const char *str);
	// 成员函数重载 > 运算符
	bool operator>(MyString &ob);
	bool operator>(const char *str);
	// 成员函数重载 < 运算符
	bool operator<(MyString &ob);
	bool operator<(const char *str);
	// 成员函数重载 == 运算符
	bool operator==(MyString &ob);
	bool operator==(const char *str);
};

MyString::MyString()
{
	str = NULL;
	size = 0;
}
MyString::MyString(const char *str)
{
	this->size = strlen(str);
	this->str = new char[this->size + 1];
	strcpy(this->str, str);
}

MyString::MyString(const MyString &ob)
{
	size = ob.size;
	this->str = new char[size + 1];
	memset(this->str, 0, size + 1);
	strncpy(this->str, ob.str, size);
}

MyString::~MyString()
{
	if (str != NULL)
	{
		delete[] str;
		str = NULL;
	}
}

int MyString::getSize()
{
	return size;
}

// 成员函数重载 [] 运算符
char& MyString::operator[](int pos)
{
	if (pos < 0 || pos >= size)
	{
		cout << "访问越界" << endl;
		exit(-1);
	}
	return str[pos];
}

//全局函数重载 << 运算符
ostream& operator<<(ostream &out, MyString str)
{
	out << str.str;
	return out;
}

//全局函数重载 >> 运算符
istream& operator>>(istream &in, MyString &ob)
{
	char buf[128] = "";
	cin >> buf;
	if (ob.str != NULL)
	{
		delete[] ob.str;
		ob.str = NULL;
	}
	ob.size = strlen(buf);
	ob.str = new char[ob.size + 1];
	memset(ob.str, 0, ob.size + 1);
	strcpy(ob.str, buf);
	return in;
}

// 成员函数重载 + 运算符
MyString MyString::operator+(MyString &ob)
{
	MyString tmp;
	tmp.size = this->size + ob.size;
	tmp.str = new char[tmp.size + 2];
	memset(tmp.str, 0, tmp.size + 2);
	

	strcpy(tmp.str, this->str);
	strcat(tmp.str, ob.str);


	return tmp;
}
MyString MyString::operator+(const char *str)
{
	MyString tmp;
	tmp.size = this->size + strlen(str);
	tmp.str = new char[tmp.size + 1];
	memset(tmp.str, 0, tmp.size + 1);

	strcpy(tmp.str, this->str);
	strcat(tmp.str, str);

	return tmp;
}

// 成员函数重载 = 运算符
MyString& MyString::operator=(MyString &ob)
{
	if (this->str != NULL)
	{
		delete[] this->str;
		this->str = NULL;
	}
	this->size = ob.size;
	this->str = new char[this->size + 1];
	memset(this->str, 0, this->size + 1);

	strcpy(this->str, ob.str);
	return *this;
}
MyString& MyString::operator=(const char *str)
{
	if (this->str != NULL)
	{
		delete[] this->str;
		this->str = NULL;
	}
	this->size = strlen(str);
	this->str = new char[this->size + 1];
	memset(this->str, 0, this->size + 1);

	strcpy(this->str, str);
	return *this;
}

// 成员函数重载 > 运算符
bool MyString::operator>(MyString &ob)
{
	if (this->str == NULL || ob.str == NULL)
		exit(-1);
	if (strcmp(this->str, ob.str) > 0)
		return true;
	return false;
}
bool MyString::operator>(const char *str)
{
	if (this->str == NULL || str == NULL)
		exit(-1);
	if (strcmp(this->str, str) > 0)
		return true;
	return false;
}
// 成员函数重载 < 运算符
bool MyString::operator<(MyString &ob)
{
	if (this->str == NULL || ob.str == NULL)
		exit(-1);
	if (strcmp(this->str, ob.str) < 0)
		return true;
	return false;
}
bool MyString::operator<(const char *str)
{
	if (this->str == NULL || str == NULL)
		exit(-1);
	if (strcmp(this->str, str) < 0)
		return true;
	return false;
}

// 成员函数重载 == 运算符
bool MyString::operator==(MyString &ob)
{
	if (this->str == NULL || ob.str == NULL)
		exit(-1);
	if (strcmp(this->str, ob.str) == 0)
		return true;
	return false;
}
bool MyString::operator==(const char *str)
{
	if (this->str == NULL || str == NULL)
		exit(-1);
	if (strcmp(this->str, str) == 0)
		return true;
	return false;
}

int main()
{
	MyString str = "Hello World!";

	cout << str[6] << endl;
	str[6] = 'Y';
	cout << str[6] << endl;

	cout << str << endl;

	MyString str2;
	cin >> str2;
	cout << str2;


	MyString str3 = "hello";
	MyString str4 = "world";
	cout << str3 + str4 << endl;
	cout << str3 + "Lion" << endl;

	MyString str5 = "str5";
	MyString str6 = "str6";
	cout << str6 << endl;
	str6 = str5;
	cout << str6 << endl;
	str6 = "hi,str6";
	cout << str6 << endl;


	if (str5 > str6)
		cout << "str5 > str6" << endl;
	else
		cout << "str5 <= str6" << endl;

	return 0;
}

八、仿函数:重载函数调用运算符 ()

重载 () 运算符一般用于为算法提供策略。当对象或匿名对象和 () 结合时 会触发重载函数调用运算符。
这种重载() 的对象,也称为仿函数。

示例:

#include <iostream>
using namespace std;

class Print {
public:
	void operator() (const char *str){
		cout << str << endl;
	}
};

int main()
{
	Print obj;
	obj("hi,仿函数");

	Print()("匿名对象调用");

	return 0;
}

输出:

hi,仿函数
匿名对象调用

九、智能指针(指针运算符 *、-> 重载)

智能指针主要解决堆区空间的对象释放问题。

示例:

#include <iostream>
using namespace std;

class Data {
public:
	Data() 
	{
		cout << "Data无参构造" << endl;
	}
	~Data()
	{
		cout << "Data析构函数" << endl;
	}
	void func()
	{
		cout << "Data func" << endl;
	}
};

// 智能指针类,为Data服务
class SmartPointer {
private:
	Data *p;
public:
	SmartPointer(Data *p)
	{
		this->p = p;
	}
	~SmartPointer()
	{
		delete p;
	}
	// 重载->运算符
	Data* operator->()
	{
		return p;
	}
	Data& operator*()
	{
		return *p;
	}
};

int main()
{
	SmartPointer sp(new Data);

	//sp.operator->()->func();
	sp->func();
	(*sp).func();

	return 0;
}

输出:

Data无参构造
Data func
Data func
Data析构函数

十、不要重载 && 和 || 运算符

建议不去重载operator 和 operator || 的原因是 无法在这两种情况下实现内置操作符的完整语义。内置版本特殊之处在于:内置版本的 && 和 || 会首先计算左边的表达式,如果这完全能够决定结果,就不需要计算右边的表达式了,而且能够保证不需要。而函数调用总是在函数执行前对所有参数进行求值。

示例:

class Complex {
public:
	int flag;
public:
	Complex(int flag)
	{
		this->flag = flag;
	}
	// 重载 +=运算符
	Complex& operator+=(Complex& cmplx)
	{
		this->flag = this->flag + cmplx.flag;
		return *this;
	}
	// 重载 && 运算符
	bool operator&&(Complex& cmplx)
	{
		return this->flag && cmplx.flag;
	}
};

int main()
{
	Complex com0(0);// flag=0
	Complex com1(1);// flag=1
	/*
	* 原来的情况:应该从左边往右边运算,左边为假则退出运算,结果为假
	* 现在却是:先运算(com0 += com1),导致com0的flag结果为(com0 += com1)的值
	* com0.flag=1,从而输出了 true。
	*/
	if (com0 && (com0 += com1))
	{
		cout << "true" << endl;
	}
	else
	{
		cout << "false" << endl;
	}

	return 0;
}

总结

C++重载运算符是一种允许程序员自定义运算符行为的机制。通过重载运算符,我们可以定义自己的类类型,并使其支持像加、减、乘等运算符,以及比较运算符等。

在 C++ 中,有些运算符可以被重载(如 +, -, *, / 等),而有些则不能被重载(如 ., ?: 等)。对于可以被重载的运算符,我们只需要按照一定的规则来实现相应的函数即可。

  1. 重载函数必须是一个成员函数或者友元函数。如果是成员函数,则第一个参数必须是当前对象的引用或指针;如果是友元函数,则没有这个限制。

  2. 不同的运算符要求不同的参数个数和类型。例如,二元操作符通常需要两个参数,一元操作符只需要一个参数。

  3. 运算符不能改变其操作数的值。也就是说,在执行完某个操作之后,原来的操作数必须保持不变。

  4. 除了赋值运算符外,其他所有重载操作都应该返回新对象或对象引用。

  5. 如果你想使用默认参数,则应该将它们放在最后一个形参列表中,并在声明和定义中都指定它们。

  6. 可以使用 const 关键字来表示函数不会改变对象的状态。这在一些情况下非常有用,例如定义比较运算符时。

  7. 重载运算符必须满足所有运算符本身的语义和优先级规则,否则可能会导致意外的结果。

重载运算符是 C++ 中一个非常强大的机制,可以让我们更好地控制类类型对象之间的行为。
在这里插入图片描述

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

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

相关文章

leetcode257. 二叉树的所有路径(java)

二叉树的所有路径 leetcode257. 二叉树的所有路径题目描述DFS深度优先遍历 二叉树专题 leetcode257. 二叉树的所有路径 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problems/binary-tree-paths 题目描述 给你一个二叉树的根节…

【系统开发】尚硅谷 - 谷粒商城项目笔记(十一):K8S

文章目录 K8s简介架构原理核心概念控制平面组件&#xff08;Control Plane Components&#xff09;kube-apiserveretcdkube-schedulerkube-controller-managercloud-controller-manager Node 组件kubeletkube-proxy容器运行时&#xff08;Container Runtime&#xff09; 插件&a…

Gee 项目复现

序言 复现&#xff1a;原链接 一个Web框架需要支持的功能&#xff0c; 路由&#xff0c;请求到响应函数的映射&#xff0c;支持动态路由如hello/:name,hello/*模板&#xff0c;使用内置模板引擎渲染机制。鉴权&#xff1a;分组插件&#xff1a;中间件 第一天 HTTP基础 启动…

基于边界点优化和多步路径规划的机器人自主探索

论文题目&#xff1a;Autonomous Robotic Exploration Based on Frontier Point Optimization and Multistep Path Planning 中文题目&#xff1a;基于边界点优化和多步路径规划的机器人自主探索 作者&#xff1a;Baofu Fang &#xff1b;Jianfeng Ding ; Zaijun Wang 作者机…

5.5.2 IPv6数据报格式

5.5.2 IPv6数据报格式 首先我们来回忆一下IPv4数据报首部格式&#xff08;5.2.3 IP数据报&#xff08;一&#xff09;IP数据报的格式&#xff09;&#xff0c;包括20个字节的固定部分和长度可变的选项部分&#xff0c;如图 红色方框标注的是在IPv6中会消失的字段&#xff0c;椭…

小白也会的------新建Python虚拟环境,查看该虚拟环境的路径,将该虚拟环境的所有库和版本号导出到一个 requirements.txt 文件中

我的目录标题 1、新建Python虚拟环境2、查看该虚拟环境的路径3、将该虚拟环境的所有库和版本号导出到一个 requirements.txt 文件中4、如果你只需要将当前虚拟环境中安装的所有库和版本号导出到一个 requirements.txt 文件中&#xff0c;而不需要包括每个库的来源&#xff0c;可…

KMP算法基础

前言 KMP算法是我们数据结构串中最难也是最重要的算法。难是因为KMP算法的代码很优美简洁干练&#xff0c;但里面包含着非常深的思维。真正理解代码的人可以说对KMP算法的了解已经相当深入了。而且这个算法的不少东西的确不容易讲懂&#xff0c;很多正规的书本把概念一摆出直接…

C++——命名空间(namespace)

目录 1. C语言命名冲突 2. 命名空间定义 3. 命名空间使用 可能大家在看别人写的C代码中&#xff0c;在一开始会包这个头文件&#xff1a;#include<iostream> 这个头文件等价于我们在C语言学习到的#include<stdio.h>&#xff0c;它是用来跟我们的控制台输入和输出…

带你见见红黑树-概念+插入篇

写的不好&#xff0c;见谅~ 目录 概念理解 红黑树规则 AVL树与红黑树的相爱相杀 红黑树的插入时的上色与旋转。 不上色&#xff08;shǎi&#xff09; 情况一&#xff1a;空树 情况二&#xff1a;非空树&#xff0c;父节点为黑 上色&#xff08;shǎi&#xff09; 情况…

【Linux】深入理解文件系统

系列文章 收录于【Linux】文件系统 专栏 关于文件描述符与文件重定向的相关内容可以移步 文件描述符与重定向操作。 可以到 浅谈文件原理与操作 了解文件操作的系统接口。 想深入理解文件缓冲区还可以看看文件缓冲区。 目录 系列文章 磁盘 结构介绍 定位数据 抽象管理…

【Linux】MySQL 高级 SQL 语句 (二)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 MySQL 高级 SQL 语句 连接查询CREATE VIEW 视图UNION 联集交集值无交集值CASE空值(NULL) 和 无值() 的区别正则表达式 连接查询 mysql> select * from xjz; #xjz表格 ---…

Linux5.8 MySQL主从复制与读写分离

文章目录 计算机系统5G云计算第四章 LINUX MySQL主从复制与读写分离一、概述及原理1&#xff09;什么是读写分离2&#xff09;为什么要读写分离呢3&#xff09;什么时候要读写分离4&#xff09;主从复制与读写分离5&#xff09;mysql支持的复制类型6&#xff09;主从复制的工作…

Rust语言从入门到入坑——(5)Rust 所有权

文章目录 0 引入1、所有权2、内存和分配3、移动与克隆3.1、移动3.2、克隆 4、引用与租借4.1、引用4.1、垂悬引用 5、函数中变量5.1 参数变量5.2 、返回值变量 0 引入 主要介绍Rust所有权的知识&#xff0c;涉及到变量的作用域&#xff0c;内存释放机制&#xff0c;移动&#x…

Python|Pyppeteer启动浏览器窗口,右侧出现空白区域怎么解决?(13)

前言 本文是该专栏的第13篇,结合优质项目案例持续分享Pyppeteer的干货知识,记得关注。 有些同学可能在使用pyppeteer的时候,在配置项里面,明明已经设置好了窗口最大化,而启动Chromium窗口,打开的窗口最右侧却是一大片空白区域,具体如下图所示: 那么,出现上述情况,需…

AutoGPT 英文版安装过程

自从2022年11月chatGPT的发布3.0GPT大模型&#xff0c;在中国掀起一股AI学习热潮&#xff0c;国内百度2023年4月份发布文心一言&#xff0c;把AI推上另一个高潮&#xff0c;最直接的是问答&#xff0c;我输入一句话&#xff0c;AI帮生成一段文字或一个视频&#xff0c;但是国内…

畅捷通T+ 反序列化漏洞复现(QVD-2023-13615)

0x01 产品简介 畅捷通 T 是一款基于互联网的新型企业管理软件&#xff0c;功能模块包括&#xff1a;财务管理、采购管理、库存管理等。主要针对中小型工贸和商贸企业的财务业务一体化应用&#xff0c;融入了社交化、移动化、物联网、电子商务、互联网信息订阅等元素。 0x02 漏…

Chat2DB数据AI工具开源!对数据分析师行业影响如何?

大家好&#xff0c;我是千与千寻&#xff0c;千寻目前在互联网公司担任算法工程师&#xff0c;也要经常性的和数据打交道。那么数据都存放在哪里&#xff1f;当然是数据库啦&#xff01; 说到数据库&#xff0c;我们就不得不提到一种编程语言——SQL数据语言&#xff0c;后端程…

2023年最新项目管理工具排名推荐,助你提升项目效率!

在当今快速发展的互联网时代&#xff0c;项目管理工具已经成为了越来越多企业和团队必不可少的工具之一。好的项目管理工具能够帮助团队更加高效地协同工作&#xff0c;提高工作效率&#xff0c;节省时间和成本&#xff0c;从而使得整个项目可以更快地达成预期目标。现在让我们…

微信为什么使用 SQLite 保存聊天记录?

概要 SQLite 是一个被大家低估的数据库&#xff0c;但有些人认为它是一个不适合生产环境使用的玩具数据库。事实上&#xff0c;SQLite 是一个非常可靠的数据库&#xff0c;它可以处理 TB 级的数据&#xff0c;但它没有网络层。接下来&#xff0c;本文将与大家共同探讨 SQLite 在…

【Diffusion模型系列1】DDPM: Denoising Diffusion Probabilistic Models

0. 楔子 Diffusion Models(扩散模型)是在过去几年最受关注的生成模型。2020年后&#xff0c;几篇开创性论文就向世界展示了扩散模型的能力和强大: Diffusion Models Beat GANs on Image Synthesis(NeurIPS 2021 Spotlight, OpenAI团队, 该团队也是DALLE-2的作者)[1] Various…