【C++】类的6个默认成员函数

目录

1. 类的6个默认成员函数

2. 构造函数

3. 析构函数

4. 拷贝构造函数

5. 运算符重载

5.1运算符重载

5.2赋值运算符重载

 5.3前置++和后置++重载

5.4日期类的实现

6. const成员函数

7. 取地址及const取地址操作符重载


1. 类的6个默认成员函数

对于一个空类,编译器会自动生成以下6个默认成员函数

2. 构造函数

构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,以保证每个数据成员都有一个合适的初始值,并且在对象整个生命周期内只调用一次

构造函数的主要任务不是开空间创建对象而是初始化对象

构造函数的特性:

1️⃣函数名和类名相同

2️⃣无返回值

3️⃣对象实例化时编译器自动调用对应的构造函数

4️⃣构造函数可以重载

调用无参构造函数初始化对象时,对象后面不用跟括号,否则会和函数声明混淆;

5️⃣如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义则编译器不再自动生成

编译器生成的默认构造函数:

在上面的日期类中,我们创建了一个对象,通过默认构造函数初始化后,_year,_month,_day中仍是随机值,那编译器生成的默认构造函数的意义是什么呢?

C++中把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类型,如int、char等;自定义类型就是我们使用关键字class/struct/union等自己定义的类型。编译器生成的默认构造函数会对自定义类型成员调用它的默认构造函数,而内置类型不作处理,C++11中,针对内置类型成员不初始化的缺陷,打了补丁:内置类型成员变量在类声明时可以给默认值

定义如下一个类: 

class Time
{
public:
	Time()
	{
		cout << "调用构造函数Time()" << endl;
		_hour = 0;
		_minute = 0;
		_second = 0;
	}
private:
	int _hour;
	int _minute;
	int _second;
};

在日期类中添加我们自定义类型的一个成员变量_time,调试可以发现,创建一个对象时,会调用自定义类型成员变量的构造函数,完成初始化。

内置类型成员变量在类声明时可以给默认值

实际上这种方式是给内置类型的成员变量一个缺省值

内置类型的成员变量初始化: 

6️⃣无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认的构造函数只能有一个,若存在多个,则调用时存在二义性。无参构造函数全缺省的构造函数编译器默认生成的构造函数,都可以认为是默认构造函数

默认构造函数不传参就可以调用的构造函数

3. 析构函数

析构函数和构造函数的功能相反,对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。析构函数不是完成对对象本身的销毁,局部对象的销毁工作是由编译器完成的

析构函数的特性:

1️⃣析构函数名是在类名前加上~

2️⃣无参数无返回值类型,因此析构函数不支持重载

3️⃣一个类只能有一个析构函数,若未显式定义,则编译器会自动生成默认的析构函数

4️⃣对象的生命周期结束时,系统自动调用析构函数

5️⃣编译器生成的默认析构函数,对自定义类型成员调用它的析构函数

📖Note:

当创建的Date类对象销毁时,要保证其内部所有的成员都可以被销毁,test1函数中没有直接调用Time类的析构函数,而是调用Date类的析构函数(编译器自动生成的),Date类的析构函数中才会调用Time类的析构函数。

创建哪个类的对象则调用该类的构造函数,销毁哪个类的对象则调用该类的析构函数

6️⃣如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如Date类;有资源申请时,需要自己写析构函数,否则会造成资源泄露,比如Stack类

4. 拷贝构造函数

拷贝构造函数只有单个形参该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用

拷贝构造函数的特性:

1️⃣拷贝构造函数是构造函数的一个重载形式

2️⃣拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值传参的方式编译器会直接报错,因为会引发无穷递归调用(一次传值传参就调用一次拷贝构造)

传值传参引发的无穷递归调用

函数调用时,形参是实参的一份临时拷贝,在传值传参的过程中,会产生一个临时中间变量,先将d1拷贝给这个临时变量,这次拷贝会调用拷贝构造函数,而拷贝构造函数的传传参方式是传值传参,所以每次调用拷贝构造都会产生临时变量,调用拷贝构造函数,因此引发了无穷的函数调用。传参过程如下图:

 

3️⃣若未显式定义,编译器会自动生成默认的拷贝构造函数。默认的拷贝构造函数对内置类型的成员变量按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝;对自定义类型的成员变量通过调用其拷贝构造函数完成拷贝

class Stack
{
public:
	//构造函数
	Stack(size_t capacity = 10)
	{
		_array = (DataType*)malloc(sizeof(DataType) * capacity);
		if (nullptr == _array)
		{
			perror("malloc failed");
			return;
		}
		_capacity = capacity;
		_top = 0;
	}
	//析构函数
	~Stack()
	{
		if (_array)
		{
			free(_array);
			_array = nullptr;
			_capacity = 0;
			_top = 0;
		}
	}

	//压栈
	void Push(const DataType& data)
	{
		//扩容
		CheckCapacity();
		_array[_top] = data;
		++_top;
	}

private:
	//扩容
	void CheckCapacity()
	{
		//栈满
		if (_top == _capacity)
		{
			int newcapacity = _capacity * 2;
			DataType* tmp = (DataType*)realloc(_array, newcapacity * sizeof(DataType));
			if (tmp == NULL)
			{
				perror("realloc failed\n");
				return;
			}
			_array = tmp;
			_capacity = newcapacity;
		}
	}
private:
	//变量定义
	DataType* _array;
	size_t _capacity;
	size_t _top;
};

如上图,当我们没有显式定义拷贝构造函数,使用系统自动生成的拷贝构造函数时,对于栈类,一次拷贝构造后,栈s1和栈s2指向了同一块内存空间

程序退出时,栈s1和栈s2需要销毁,后定义变量的先销毁,即s2先销毁,调用析构函数,将这块内存空间释放,s2再销毁,调用析构函数,也要释放这块空间,但此时这块空间已经被释放了,因此程序会崩溃

以上过程是一次浅拷贝的过程;对于栈类,需要显式定义拷贝构造函数以实现深拷贝,即使用栈s1拷贝构造栈s2时,需要开辟和s1相同大小的空间,并将s1中的值拷贝过来,这样栈s1和栈s2都拥有自己的空间,二者相互独立,不影响后续的操作

📖Note:

类中如果没有涉及资源申请时,拷贝构造函数可以不显式定义,如日期类;一旦类中涉及资源申请,则一定要显式定义拷贝构造函数,否则拷贝就是浅拷贝,如栈

总结:需要写析构函数的类,都要显式定义深拷贝的拷贝构造函数,其他类使用默认生成的拷贝构造函数即可

4️⃣拷贝构造函数典型的调用场景

  • 使用已存在对象创建新对象(上述例子)
  • 函数参数类型为类类型对象
  • 函数返回值类型为类类型对象

总结:

为了提高程序效率,对象传参时尽量使用引用传参,返回时根据实际情况尽量使用引用返回

5. 运算符重载

5.1运算符重载

C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数

函数原型:返回值类型 operator操作符(参数列表)

📖Note:

  1. 不能通过连接其他符号来创建新的操作符,如operator@
  2. 重载操作符必须有一个类类型参数
  3. 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不能改变其含义
  4. 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this指针
  5. 不能重载的5个运算符:⑴ .*  、⑵ ::   、 ⑶sizeof  、⑷? :  、⑸​​​​​​​​​​​​​​ .

操作符==的重载 

全局的operator==存在的问题:私有的成员变量不能访问;如果将成员变量设置成公有的,则封装性不能保证

解决方案:

  1. 直接重载成成员函数
  2. 定义一个公有的成员函数GetYear(),获取私有的成员变量
  3. 使用友元

1️⃣直接重载成成员函数

此时形参列表中只需要显式定义一个参数,因为第一个参数为隐含的this指针

//日期类
class Date
{
public:
    //操作符==重载
	bool operator==(const Date& d)
	{
		return _year == d._year
			&& _month == d._month
			&& _day == d._day;
	}
	
private:
	int _year;
	int _month;
	int _day;
};

2️⃣定义一个公有的成员函数GetYear(),获取私有的成员变量

注意获取成员函数的函数需要用const修饰

//日期类
class Date
{
public:
	//获取私有成员函数
	int GetYear(const Date& d) const
	{
		return d._year;
	}
	int GetMonth(const Date& d) const
	{
		return d._month;
	}
	int GetDay(const Date& d) const
	{
		return d._day;
	}
	
private:
	int _year;
	int _month;
	int _day;
};
//全局的operator==
bool operator==(const Date& d1,const Date& d2)
{
	return d1.GetYear(d1) == d2.GetYear(d2)
		&& d1.GetMonth(d1)== d2.GetMonth(d2)
		&& d1.GetDay(d1) == d2.GetDay(d2);
}

int main()
{
	Date d1(2024, 2, 9);
	Date d2(2024, 2, 10);

	cout << (d1 == d2) << endl; //输出0

	return 0;
}

3️⃣使用友元

//日期类
class Date
{
public:
	//全缺省的构造函数
	Date(int year = 2024, int month = 2, int day = 8)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	//拷贝构造
	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

	//声明全局的operator==为友元函数
	friend bool operator==(const Date& d1, const Date& d2);
	
private:
	int _year;
	int _month;
	int _day;
};
bool operator==(const Date& d1, const Date& d2)
{
	return d1._year == d2._year
		&& d1._month == d2._month
		&& d1._day == d2._day;
}

5.2赋值运算符重载

1️⃣赋值运算符重载格式:

  • 参数类型:const T&,引用传参可以提高传参效率(T表示数据类型)
  • 返回值类型:T&,引用返回可以提高返回的效率,有返回值的目的是为了支持连续赋值
  • 检测是否自己给自己赋值
  • 返回*this:要符合连续赋值的含义
//日期类
class Date
{
public:
	//全缺省的构造函数
	Date(int year = 2024, int month = 2, int day = 8)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	//拷贝构造
	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	//赋值运算符重载
	Date& operator=(const Date& d)
	{
        //避免自己给自己赋值
		if (this != &d)
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this;
	}
	//打印
	void print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
	
private:
	int _year;
	int _month;
	int _day;
};

赋值运算符重载:

参数列表中,只写了一个参数,实际上有两个参数,第一个参数是隐含的this指针,赋值操作符需要区分左右操作数,第一个参数是左操作数,第二个参数是右操作数

返回值:this指针是左操作数的地址,返回*this,即左操作数的值,除了赋值重载函数的作用域,左操作数这个对象还在,因此可以采用引用返回,避免一次拷贝构造,提高效率

返回值的类型是类类型,不需要加const,因为可能会对返回值做修改

 

连续赋值的情况:上述代码中,先执行d5 = d4,调用赋值重载,d5=d4转换为Date& operator (&d5,&d4),把d4的值拷贝给d5,并返回左操作数d5,因此d5 = d4这个表达式的值为d5,因此接下来执行的就是d6 = d5,即把d5的值拷贝给d6,和上述同样的操作,完成了一次连续赋值

2️⃣赋值运算符只能重载成类的成员函数而不能重载成全局函数

赋值运算符如果在类内不显式实现,编译器会生成一个默认的赋值运算符重载。此时用户在类外实现的全局的赋值运算符重载会和编译器在类内生成的默认赋值运算符重载产生冲突,故赋值运算符重载只能是类的成员函数

3️⃣用户没有显式实现时,编译器会生成一个默认的的赋值运算符重载,以值的方式逐字节拷贝

📖Note:

内置类型的成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符重载完成赋值

栈的赋值重载:拷贝构造不能完成使用一个栈初始化另一个栈的操作,因为拷贝构造使两个栈指向了同一块空间,程序运行结束时析构两次会导致程序崩溃

当我们没有显式定义赋值运算符重载时,使用编译器在类内生成的默认赋值运算符重载,以值的方式逐字节拷贝每个成员变量的值,由上图,两个栈赋值时会发生错误

以值的方式逐字节拷贝,会导致栈s1和栈s2中的指针同时指向s2指向的空间,而原来s1指向的空间并没有释放,导致了内存泄漏;同时指向的这同一块空间会在程序结束时被析构两次

解决方案:在栈类内显式定义赋值运算符重载,为两个栈开辟不同的空间,使二者的结构独立

Stack& operator=(const Stack& st)
{
	if (this != &st)
	{
		free(_array);//释放原来空间
		_array = (DataType*)malloc(sizeof(DataType) * st._capacity);
		if (_array == nullptr)
		{
			perror("malloc failed");
			exit(-1);
		}
		memcpy(_array, st._array, sizeof(DataType) * st._top);
		_top = st._top;
		_capacity = st._capacity;
	}
	return *this;
}

if语句的作用是避免同一个栈自己给自己赋值

释放被赋值的对象原来空间后,开辟和右操作数对应的栈相同大小的空间,并将栈中的数据拷贝过去,就实现了两个栈独立存在

返回*this是为了可以实现连续的赋值操作

 5.3前置++和后置++重载

前置++:先++后使用 ===>返回值是++后的值

this指向的对象函数结束后不会销毁,因此可以使用引用返回

后置++:先使用后++ ===>返回值是++前的值

前置++和后置++都是一元运算符,为了使前置++和后置++能正确重载,C++规定:后置++运算符重载时多增加一个int类型的参数,但调用函数时该参数不用传递,由编译器自动传递。后置++要返回旧值,因此需要创建临时变量存储++前的值,最终返回的也是旧值,因为旧值存放在临时变量中,因此只能传值返回,不能引用返回

//日期类
class Date
{
public:
	//构造函数
	Date(int year = 2024, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	//打印
	void print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
	//前置++
	Date& operator++()
	{
		_day += 1;
		return *this;
	}

	//后置++
	Date operator++(int)
	{
		Date tmp(*this);//拷贝构造,存储++前的数据
		_day += 1;
		return tmp;
	}

private:
	int _year;
	int _month;
	int _day;
};

📖Note:

对于后置++来说,它比前置++多了两次拷贝,一次调用拷贝构造,一次传值返回;因此对于自定义类型的变量,尽量使用前置++

前置--和后置--的实现和++类似

//前置--
Date& operator--()
{
	_day -= 1;
	return *this;
}

//后置--
Date operator--(int)
{
	Date tmp(*this);//拷贝构造,存储++前的数据
	_day -= 1;
	return tmp;
}

5.4日期类的实现

//日期类
class Date
{
public:

	Date(int year = 2024, int month = 2, int day = 6)
	{
		_year = year;
		_month = month;
		_day = day;
		//cout << "调用构造函数" << endl;
	}
	//拷贝构造函数
	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
		//cout << "调用拷贝构造函数" << endl;
	}
	//析构函数
	~Date()
	{
		//cout << "调用析构函数" << endl;
	}

	//打印
	void print() const
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

private:
	//内置类型
	int _year = 1 ;
	int _month = 1;
	int _day = 1;
};

以上是一个简单的日期类,我们已经实现类赋值运算符的重载,操作符==的重载,以下我们将实现>、>=、<、<=、+、+=、-、-=等运算符的重载

 1️⃣>和>=的重载

//>的重载
bool operator>(const Date& d)
{
	if (_year > d._year)
	{
		return true;
	}
	else if (_year == d._year && _month > d._month)
	{
		return true;
	}
	else if (_year == d._year && _month == d._month && _day > d._day)
	{
		return true;
	}
	return false;
}
//>=的重载
bool operator>=(const Date& d)
{
	return *this > d || *this == d;
}

2️⃣<和<=的重载

//<的重载
bool operator<(const Date& d)
{
	if (_year < d._year)
	{
		return true;
	}
	else if (_year == d._year && _month < d._month)
	{
		return true;
	}
	else if (_year == d._year && _month == d._month && _day < d._day)
	{
		return true;
	}
	return false;
}
//<=的重载
bool operator<=(const Date& d)
{
	return *this < d || *this == d;
}

3️⃣+和+=的重载

日期类对象的假发涉及进位问题,因为存在大月小月,平年闰年问题,我们可以使用月份数组来获取某年某个月的天数

+=等重载可以引用返回,+的重载要返回临时变量中的值,只能传值返回

//月份数组
int GetMonthDay(int year, int month)
{
	int MonthDayArrary[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
	//闰年
	if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
	{
		return 29;
	}
	else
	{
		return MonthDayArrary[month];
	}
}
//+=的重载
Date& operator+=(int day)
{
	_day += day;//日期+day天
	//天数超出
	while (_day > GetMonthDay(_year, _month))
	{
		_day -= GetMonthDay(_year, _month);
		_month++;
		//月份超出
		if (_month == 13)
		{
			++_year;
			_month = 1;//年满之后,置1月份
		}
	}
	return *this;
}
//+的重载
Date operator+(int day)
{
	Date ret(*this);//拷贝构造
	ret += day;
	return ret;
}

4️⃣-和-=的重载:类似于+和+=,不够减则借位

//-=的重载
Date& operator-=(int day)
{
	_day -= day;//日期+day天
	//本月天数不够减,需要借位
	while (_day < 0)
	{
		--_month;
		//本年月数不够减,需要借位
		if (_month == 0)
		{
			--_year;
			_month = 12;//新的一年
		}
		_day += GetMonthDay(_year, _month);
	}
	return *this;
}
//-的重载
Date operator-(int day)
{
	Date ret(*this);//拷贝构造
	ret -= day;
	return ret;
}

+=、+、-、-=重载的完善:当某个日期加的天数是一个负数时,需要对这种情况进行处理,加一个负数就是减去这个负数的相反数(一个正数),调用减法的重载即可;当某个日期减的天数是一个负数时,相当于加去这个负数的相反数(一个正数),调用加法的重载即可;


//+=的重载
Date& operator+=(int day)
{
	//加一个负数===>减其相反数
	if (day < 0)
	{
		return *this -= abs(day);
	}
	_day += day;//日期+day天
	//天数超出
	while (_day > GetMonthDay(_year, _month))
	{
		_day -= GetMonthDay(_year, _month);
		_month++;
		//月份超出
		if (_month == 13)
		{
			++_year;
			_month = 1;//年满之后,置1月份
		}
	}
	return *this;
}
//+的重载
Date operator+(int day)
{
	Date ret(*this);//拷贝构造
	//加一个负数===>减其相反数
	if (day < 0)
	{
		ret -= abs(day);
		return ret;
	}
	ret += day;
	return ret;
}

//-=的重载
Date& operator-=(int day)
{
	//减一个负数 ===>加其相反数
	if (day < 0)
	{
		return *this += abs(day);
	}
	_day -= day;//日期+day天
	//本月天数不够减,需要借位
	while (_day < 0)
	{
		--_month;
		//本年月数不够减,需要借位
		if (_month == 0)
		{
			--_year;
			_month = 12;//新的一年
		}
		_day += GetMonthDay(_year, _month);
	}
	return *this;
}
//-的重载
Date operator-(int day)
{
	Date ret(*this);//拷贝构造
	//减一个负数 ===>加其相反数
	if (day < 0)
	{
		ret += abs(day);
		return ret;
	}
	ret -= day;
	return ret;
}

6. const成员函数

const成员函数:将const修饰的成员函数称为const成员函数,const修饰类成员函数,实际修饰的是该成员函数隐含的this指针,表明该成员函数不能对类的任何成员进行修改

编译器对const成员函数的处理如下:

一些const修饰变量或函数时的权限问题:

以上代码属于const修饰时的权限放大问题:把一个使用const修饰的变量作为实参传递给一个没有const修饰的形参,编译器报错

以上代码中,成员函数使用const修饰后, this指针指向的对象为const Date类型的,因此实参指向的对象可以是const Date类型的,也可以是Date类型的,因为权限平移和权限缩小都是允许的

总结:

  1. const对象不可以调用非const成员函数(权限放大不允许)
  2. 非const对象可以调用const成员函数(权限缩小允许)
  3. const成员函数内不可以调用其他的非const成员函数(权限放大不允许)
  4. 非const成员函数内可以调用其他的const成员函数(权限缩小允许)

凡是内部不改变成员变量,也就是*this对象数据的,这些成员函数都应该加const修饰

7. 取地址及const取地址操作符重载

这两个运算符一般不需要重载,使用编译器默认生成取地址的重载即可

//日期类
class Date
{
public:
	//取地址重载
	Date* operator&()
	{
		return this;
	}
	//const修饰的取地址操作符重载,给const对象调用
	const Date* operator&() const
	{
		return this;
	}
private:
	int _year;
	int _month;
	int _day;
};

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

零基础学Python之Unitest模块

1.unittest简介及入门案例 &#xff08;1&#xff09;什么是Unitest Unittest是Python自带的单元测试框架&#xff0c;不仅适用于单元测试&#xff0c;还可用于Web、Appium、接口自动化测试用例的开发与执行。该测试框架可组织执行测试用例&#xff0c;并且提供丰富的断言方法…

Git合并多个commit

git rebase -i commitId 假设想要合并最后3个commit&#xff0c; git log显示 commit id 1 commit id 2 commit id 3 commit id 4 则执行git rebase -i commitId4. 注意是4&#xff0c;不是3. 然后&#xff0c;pick最老的commit (commit id 3). https://blog.csdn.net/qiao…

在 VMware 虚拟机上安装 CentOS系统 完整(全图文)教程

一、前期准备&#xff1a; 1.安装VMware 虚拟机软件&#xff08;不在讲解&#xff0c;可自行去下载安装&#xff09;。官网&#xff1a;https://customerconnect.vmware.com/cn/downloads/details?downloadGroupWKST-PLAYER-1750&productId1377&rPId111471 2.下载iso…

女博士眼里的“科学的尽头是玄学”

点击文末“阅读原文”即可参与节目互动 剪辑、音频 / 卷圈 运营 / SandLiu 卷圈 监制 / 姝琦 封面 / 姝琦Midjourney 产品统筹 / bobo 过年啦&#xff0c;拜年啦&#xff0c;吉祥话说起来吖&#xff01;祝大家龙腾四海、龙马精神、龙飞凤舞、龙年大吉&#xff01;不知道…

一条 SQL 更新语句是如何执行的?

之前你可能经常听 DBA 同事说&#xff0c;MySQL 可以恢复到半个月内任意一秒的状态&#xff0c;惊叹的同时&#xff0c;你是不是心中也会不免会好奇&#xff0c;这是怎样做到的呢&#xff1f; 我们先从一条更新语句讲起&#xff0c;首先创建一个表&#xff0c;这个表有一个主键…

内网穿透工具

1. nps-npc 1.1 简介 nps是一款轻量级、高性能、功能强大的内网穿透代理服务器。目前支持tcp、udp流量转发&#xff0c;可支持任何tcp、udp上层协议&#xff08;访问内网网站、本地支付接口调试、ssh访问、远程桌面&#xff0c;内网dns解析等等……&#xff09;&#xff0c…

Git、github与gitee码云

1.git核心是两个仓库&#xff1a;本地仓库和远程仓库 主要用于团队合作和代码版本控制&#xff08;个人现有版本代码出错可回溯上个提交版本的代码&#xff09; 远程仓库国际主流githut&#xff0c;但外网速度问题&#xff0c;国内可使用码云gitee github&#xff1a;https:…

奇瑞汽车,好好卖车,别趟个人是非的浑水

文 | AUTO芯球 作者 | 雷歌 这下&#xff0c;奇瑞法务部忙都忙不过来了。 一个字&#xff0c;就是&#xff0c;告&#xff01;告&#xff01;告&#xff01; 刚投诉完这家&#xff0c;又去告那家。 可是骂奇瑞的实在太多了&#xff0c;告不完&#xff0c;根本告不完。 有骂…

力扣刷题之旅:进阶篇(四)—— 滑动窗口问题

力扣&#xff08;LeetCode&#xff09;是一个在线编程平台&#xff0c;主要用于帮助程序员提升算法和数据结构方面的能力。以下是一些力扣上的入门题目&#xff0c;以及它们的解题代码。 --点击进入刷题地址 引言&#xff1a; 在编程的世界里&#xff0c;滑动窗口问题是一种…

【漏洞复现】狮子鱼CMS某SQL注入漏洞01

Nx01 产品简介 狮子鱼CMS&#xff08;Content Management System&#xff09;是一种网站管理系统&#xff0c;它旨在帮助用户更轻松地创建和管理网站。该系统拥有用户友好的界面和丰富的功能&#xff0c;包括页面管理、博客、新闻、产品展示等。通过简单直观的管理界面&#xf…

自制微信红包封面

一.前言 这不是过年了吗&#xff0c;各大平台都发放了免费的微信红包封面&#xff0c;但我老是抢不到QAQ。于是乎&#xff0c;我便想“授人以鱼不如授人以渔”&#xff0c;不如自己造个封面。 二.主要步骤 1.条件 1>创建视频号 2>过去一年发表过视频号 3>过去一…

比较6*6范围内7个点182个结构的顺序

( A, B )---6*30*2---( 1, 0 )( 0, 1 ) 让网络的输入有6个节点&#xff0c;训练集AB各由6张二值化的图片组成&#xff0c;让A中有7个点&#xff0c;让B全是0&#xff0c;收敛误差7e-4&#xff0c;收敛199次&#xff0c;统计迭代次数平均值并排序。 得到顺序为 用6个点的结构标…

re:从0开始的CSS学习之路 1. CSS语法规则

0. 写在前面 现在大模型卷的飞起&#xff0c;感觉做页面的活可能以后就不需要人来做了&#xff0c;不知道现在还有没有学前端的必要。。。 1. HTML和CSS结合的三种方式 在HTML中&#xff0c;我们强调HTML并不关心显示样式&#xff0c;样式是CSS的工作&#xff0c;现在就轮到C…

整合 Axios

大家好我是苏麟 , 今天聊一下Axios . Axios Axios 是一个基于 promise 网络请求库&#xff0c;作用于node.js 和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 XMLHttpReques…

C++ 中的模型预测控制(01/2)

目录 一、说明二、MPC原理说明三、分解算法的来源并显示关键特征&#xff0c;四、C 实现说明五、平衡 Q 和 R六、资源下载地址 一、说明 以下文章介绍了应用模型预测控制器的简单控制系统方法。本文讨论了这种控制的基本机制&#xff0c;该机制适用于各种工程领域。 MPC 涉及对…

MPLS VPN功能组件(3)

私网标签分配 通过MPBGP为VPNv4路由分配内层标签 PE从CE接收到IPv4路由后&#xff0c;对该路由加上相应VRF的RD&#xff08;RD手动配置&#xff09;&#xff0c;使其成为一条VPNV4路由&#xff0c;然后在路由通告中更改下一跳属性为自己&#xff0c;通常是自己的Loopback地址…

[Java][算法 双指针]Day 02---LeetCode 热题 100---04~07

LeetCode 热题 100---04~07 第一题&#xff1a;移动零 思路 找到每一个为0的元素 然后移到数组的最后 但是需要注意的是 要在给定的数组原地进行修改 并且其他非零元素的相对顺序不能改变 我们采用双指针法 定义两个指针i和j i和j一开始分别都在0索引位置 然后判断j所…

PWM输入输出

PWM&#xff08;Pulse Width Modulation&#xff09;即脉冲宽度调制&#xff0c;在具有惯性的系统中&#xff0c;可以通过对一系列脉冲的宽度进行制&#xff0c;来等效地获得所需要的模拟参量&#xff0c;常应用于电机控速、开关电源等领域。 PWM参数 PWM 中有三个重要参数&…

关于CSDN的原力分增长规则,一点个人经验

本文章编写于 2024年2月9日 从2022年开始到现在&#xff0c;官方的原力分增减规则已经改过好几版了&#xff0c;有一些规则描述比较模糊&#xff0c;这里总结了一些个人经验。 原力值增长点&#xff1a; 1.每日发布文章一篇10分&#xff0c;两篇15分&#xff0c;上限15分&am…

Qt QML学习(一):Qt Quick 与 QML 简介

参考引用 QML和Qt Quick快速入门全面认识 Qt Widgets、QML、Qt Quick 1. Qt Widgets、QML、Qt Quick 区别 1.1 QML 和 Qt Quick 是什么关系&#xff1f; 1.1.1 从概念上区分 QML 是一种用户界面规范和标记语言&#xff0c;它允许开发人员创建高性能、流畅的动画和具有视觉吸引…