当前位置: 首页 > news >正文

类与对象(中)

类的6个默认成员函数

如果一个类中什么成员都没有,简称为空类。
空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下 6 个默认成员函数。默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。
这六个默认成员函数用户不写编译器会自动生成,下边我来一一讲解

构造函数

对于以下Date类:

class Date
{
public:void Init(int year, int month, int day){
_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};
int main()
{Date d1;d1.Init(2022, 7, 5);d1.Print();Date d2;d2.Init(2022, 7, 6);d2.Print();return 0;
}
对于 Date 类,可以通过 Init 公有方法给对象设置日期,但如果每次创建对象时都调用该方法设置信息,未免有点麻烦,那能否在对象创建时,就将信息设置进去呢?
构造函数 是一个 特殊的成员函数,名字与类名相同 , 创建类类型对象时由编译器自动调用 ,以保证每个数据成员都有 一个合适的初始值,并且在对象整个生命周期内只调用一次
特性:
 class Date{public:// 1.无参构造函数Date(){}// 2.带参构造函数Date(int year, int month, int day){_year = year;_month = month;_day = day;}private:int _year;int _month;int _day;};void TestDate(){Date d1; // 调用无参构造函数Date d2(2015, 1, 1); // 调用带参的构造函数// 注意:如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明// 以下代码的函数:声明了d3函数,该函数无参,返回一个日期类型的对象// warning C4930: “Date d3(void)”: 未调用原型函数(是否是有意用变量定义的?)Date d3();}

注意,无参的对象调用无参构造函数,传参的对象调用带参构造函数

如果类中没有显式定义构造函数,则 C++ 编译器会自动生成一个无参的默认构造函数,一旦
用户显式定义编译器将不再生成。
class Date{public:/*// 如果用户显式定义了构造函数,编译器将不再生成Date(int year, int month, int day){_year = year;_month = month;_day = day;}*/void Print(){cout << _year << "-" << _month << "-" << _day << endl;}private:int _year;int _month;int _day;};int main(){Date d1;return 0;}

如果没有显示写构造函数,编译器默认生成一个无参构造函数,不会报错,原因等会我会总结

关于编译器生成的默认成员函数,很多童鞋会有疑惑:不实现构造函数的情况下,编译器会
生成默认的构造函数。但是看起来默认构造函数又没什么用? d 对象调用了编译器生成的默
认构造函数,但是 d 对象 _year/_month/_day ,依旧是随机值。也就说在这里 编译器生成的
默认构造函数并没有什么用??
解答: C++ 把类型分成内置类型 ( 基本类型 ) 和自定义类型。内置类型就是语言提供的数据类
型,如: int/char... ,自定义类型就是我们使用 class/struct/union 等自己定义的类型,看看
下面的程序,就会发现编译器生成默认的构造函数会对自定类型成员 _t 调用的它的默认成员
函数。
class Stack
{
public:private:int* _a;int _capacity;int _top;
};// 两个栈实现一个队列
class MyQueue
{
private:Stack _pushst;Stack _popst;int _size = 1;
};int main()
{Stack st1;MyQueue mq;return 0;
}

看上面这段代码,会是什么样的结果呢

可以看到内置类型没有被处理(size用的是c++11的缺省值,没写缺省值也是随机值),mq被处理了是vs2022的版本太高了,用vs2013测试内置类型还是随机值,所以我们认为内置类型不做处理

如果栈的构造函数我们写了,看一下会发生什么

可以看到成功调用我们写的构造函数,栈的内置类型和mq的自定义类型都被初始化了

得出一个结论:我们不写编译器会生成一个默认成员函数,内置成员不做处理,自定义类型会去调用它的默认构造

c++11打了一个补丁,支持声明时给缺省值(当我们没写内置类型会默认用缺省值)

一般情况下,我们都要自己写构造函数,当成员都是自定义类型,或者声明时给了缺省值,可以考虑让编译器自己生成构造函数

1、我们不写编译默认生成那个构造函数,叫默认构造
2、无参构造函数也可以叫默认构造
3、全缺省也可以叫默认构造
可以不传参数就调用构造,都可以叫默认构造  这三个函数不能同时存在,只能存在一个
class Date
{
public:Date(){_year = 1900;_month = 1;_day = 1;}Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}
private:int _year;int _month;int _day;
};
// 以下测试函数能通过编译吗?
void Test()
{Date d1;
}

会报错,调用不明确,验证了只能有一个默认构造函数

析构函数

class Date
{
public:Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}~Date(){// Date严格来说,不需要写析构函数cout << "~Date()" << endl;}
private:// C++11支持,声明时给缺省值int _year = 1;int _month = 1;int _day = 1;
};class Stack
{
public:Stack(size_t capacity = 3){cout << "Stack(size_t capacity = 3)" << endl;_a = (int*)malloc(sizeof(int) * capacity);if (nullptr == _a){perror("malloc申请空间失败!!!");}_capacity = capacity;_top = 0;}~Stack(){cout << "~Stack()" << endl;free(_a);_capacity = _top = 0;_a = nullptr;}private:int* _a;int _capacity;int _top;
};class MyQueue
{private:Stack _pushst;Stack _popst;int _size = 1;
};// 21:17继续
int main()
{Date d1;Stack st1;MyQueue mq;return 0;
}

可以看到,三次构造,4次析构

说明析构函数原理和构造函数相似,内置类型成员不做处理,自定义类型成员会调用他的析构,并且Date类的析构可写可不写,不写和写的效果一样,但是stack这种必须写,编译器默认生成的并不会帮我们释放堆区空间,会造成内存泄漏

拷贝构造函数

特征
拷贝构造函数也是特殊的成员函数,其 特征 如下:
1. 拷贝构造函数 是构造函数的一个重载形式
2. 拷贝构造函数的 参数只有一个 必须是类类型对象的引用 ,使用 传值方式编译器直接报错 ,因为会引发无穷递归调用。
class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}// Date(const Date& d)   // 正确写法Date(const Date& d)   // 错误写法:编译报错,会引发无穷递归{_year = d._year;_month = d._month;_day = d._day;}
private:int _year;int _month;int _day;
};
int main()
{Date d1;Date d2(d1);return 0;
}

如果拷贝构造形参没有&,会造成无穷拷贝,一定要加上引用

像上边这种代码是纯粹内置类型,我们不写编译器默认生成的也会完成值拷贝,所以这种类型全是内置类型的不用写构造函数也能完成任务

下边我用代码来解释原理

#include<iostream>
using namespace std;
class Stack
{
public:Stack(size_t capacity = 3){cout << "Stack(size_t capacity = 3)" << endl;_a = (int*)malloc(sizeof(int) * capacity);if (nullptr == _a){perror("malloc申请空间失败!!!");}_capacity = capacity;_top = 0;}// Stack st2(st1);Stack(const Stack& stt){cout << "	Stack(Stack& stt)" << endl;// 深拷贝_a = (int*)malloc(sizeof(int) * stt._capacity);if (_a == nullptr){perror("malloc fail");exit(-1);}memcpy(_a, stt._a, sizeof(int) * stt._top);_top = stt._top;_capacity = stt._capacity;}~Stack(){cout << "~Stack()" << endl;free(_a);_capacity = _top = 0;_a = nullptr;}private:int* _a;int _capacity;int _top;
};class MyQueue
{Stack _pushst;Stack _popst;int _size = 0;
};int main()
{Stack st1;Stack st2(st1);MyQueue q1;MyQueue q2(q1);return 0;
}

可以看到我们写了stack的构造和拷贝构造,结果st1和st2完成了构造和拷贝构造的任务,并且st1拷贝st2是深拷贝,_a新开辟了一块堆区空间

问题来了,为什么要写拷贝构造呢,因为不写默认生成的拷贝构造只能完成值拷贝,就像刚才Date类一样,只能完成内置类型值拷贝,自定义类型如果也是值拷贝,会造成同一块空间析构两次,因为是两个对象,作用域结束都会销毁,两个对象析构2次,所以是错误的,我们要针对栈类写一个拷贝构造,目的是完成深拷贝

再来看两个栈实现一个队列的q1,q2可以看到内置类型不做处理(我们认为内置类型不做处理,有些编译器会处理为0,但还是建议认为内置不做处理更好理解规则),自定义类型又去调用它的拷贝构造

总结:

 Date 和 MyQueue 默认生成拷贝就可以用
 1、内置类型成员完成值拷贝
 2、自定义类型成员调用这个成员的拷贝构造
 Stack需要自己写拷贝构造,完成深拷贝。
 顺序表、链表、二叉树等等的类,都需要深拷贝(使用堆区空间的都需要深拷贝)

赋值运算符重载

运算符重载不是赋值重载,也不是默认成员函数,不写编译器不会默认生成,需要我们自己实现(默认实现成operator)

// 运算符重载
class Date
{
public:Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}void Print(){cout << _year << "/" << _month << "/" << _day << endl;}//private:int _year;int _month;int _day;
};bool operator>(const Date& x, const Date& y)
{if (x._year > y._year){return true;}else if (x._year == y._year && x._month > y._month){return true;}else if (x._year == y._year && x._month == y._month && x._day > y._day){return true;}return false;
}
bool operator==(const Date& x, const Date& y)
{return x._year == y._year&& x._month == y._month&& x._day == y._day;
}int main()
{Date d1;Date d2(2025, 10, 22);d1 == d2;d1 > d2;// 11:40 继续bool ret1 = d1 > d2;  // operator>(d1, d2);//编译器会转换成这个bool ret2 = d1 == d2; // operator==(d1, d2);/*int x = 1, y = 2;bool ret1 = x > y;bool ret2 = x == y;*/return 0;
}

上边将运算符重载函数实现为全局的,如果没有友元需要将私有去掉,才能访问私有内置类型

为什么会有运算符重载呢,因为我们要比较的时候,内置类型是简单类型,可以直接用各种运算符,语言自己定义,编译直接转换成指令,但自定义类型是复杂类型不支持,需要我们自己实现

赋值运算符重载
1. 赋值运算符重载格式
参数类型 const T& ,传递引用可以提高传参效率
返回值类型 T& ,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值
检测是否自己给自己赋值 返回 *this :要复合连续赋值的含义
class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}/*Date& operator=(const Date& d)
{if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;
}*/
private:int _year;int _month;int _day;
};int main()
{Date d1;Date d2(2025, 1, 1);d2=d1;return 0;
}

可以看到赋值运算符重载对于内置类型可以实现,也可以不实现,结果是一样的

赋值运算符只能重载成类的成员函数不能重载成全局函数(记住就行,本来就是在类里边实现的)

用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝
意:内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符
重载完成赋值。这个赋值重载和拷贝构造的意义可以类比理解,都是内置类型不用处理,自定义类型会调用它的复制拷贝(也就是说有深拷贝的地方就要自己实现新的赋值拷贝,从而防止析构两次,和拷贝构造一个原理)

日期类的实现

我把日期类原理给讲一下,然后把代码整这上边想看了可以看看

这是简单的求日期天数,当输入非法日期会打印日期非法

打印日期很简单

运算符重载,年月日都相等会返回True

this是d1的地址,*this是d1,返回比较的真假

比较大小,先比较年,年大即大,年相等比较月,月大即大,年月都相等比较日,日大即大,其他情况都是不符合条件返回错误

这三个都比较简单,就不赘述了

得到天数,最好写成一个函数方便得到天数,也就是已知年和月要得到日

+直接构造一个tmp,直接复用+=,后返回tmp,因为+不会改变自身,所以不返回*this

+=可以直接写+的逻辑,然后返回*this,因为自身会修改(day<0复用-=逻辑)

-=和-和+=,+是一个逻辑,就不赘述了

注意,如果返回自身*this并且返回值加引用,是因为出了作用域自定义对象不会销毁,我们加一个&,可以少拷贝一次提高效率;没有&返回的时候,因为出作用域就销毁了,所以不能加引用,会拷贝构造一次

最后再说一下前置++和后置++

这里参数是空的默认是前置++,所以返回*this,有一个int是后置++,返回构造的对象

前置--和后置--是一个道理

流插入流提取的实现

全局会重载<<流插入运算符,内置类型会自动识别类型,自定义类型的打印需要自己实现

cout的类型是ostream,是一个流,将内存的值打印到屏幕上(从内存流到屏幕上)

cin就不写了,和cout反着来,从屏幕上流入内存

这里不能设成成员函数,成员函数默认第一个参数是this,不符合cout打印的格式

这里设成友元函数进行操作,可以实现正确打印格式

注意

const成员

const 修饰的 成员函数 称之为 const 成员函数 const 修饰类成员函数,实际修饰该成员函数 隐含的 this 指针 ,表明在该成员函数中 不能对类的任何成员进行修改
记住,const在成员函数后边表示修饰*this,const在*前边表示修饰指针指向的对象,在*后边修饰指针
拿Print成员函数举例子,当是const对象时,const Date* 不能传给Date* const this 权限放大;但是可以传给const成员函数的Print()权限缩小,并且非const对象也能调用const成员函数的Print,是权限缩小
所以我么看到
总结:成员函数定义原则
1.能定义成const的成员啊函数都应该定义成const,这样 const对象(权限平移)和非const对象都可以调用
2.要修改成员变量的成员函数,不能定义成const,const对象不能调用(很合理),非const才能调用
请思考下面的几个问题:
1. const 对象可以调用非 const 成员函数吗?不能,权限扩大
2. const 对象可以调用 const 成员函数吗?可以,权限缩小
记住,权限平移或者缩小可以调用,权限扩大不行

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

就这两个东西,非const对象调用非const版本,返回非const,const对象调用const版本,返回const,一般我们不用实现,编译器默认会实现这两个成员函数

如果显示实现会调用显示实现的

没显示实现编译器会自己生成

到此类的6个默认成员函数都讲完了,如果有什么问题可以私信或者在评论区交流

感谢支持!!!

下边我把日期类的实现代码结合我们刚才讲的const和operator<<在复制一份在下边,有需要的可以看看(代码都已经测试过,没有任何问题,细节我能讲的已经全部讲到,欢迎友好交流)

日期类完整代码

Date.h


#include<iostream>
#include<assert.h>
using namespace std;class Date
{
public:Date(int year = 1, int month = 1, int day = 1);void Print() const;int GetMonthDay(int year, int month);bool operator==(const Date& y) const;bool operator!=(const Date& y) const;bool operator>(const Date& y) const;bool operator<(const Date& y) const;bool operator>=(const Date& y) const;bool operator<=(const Date& y) const;int operator-(const Date& d) const;Date& operator+=(int day);Date operator+(int day) const;Date& operator-=(int day);Date operator-(int day) const;Date& operator++();Date operator++(int);Date& operator--();Date operator--(int);friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);
private:int _year;int _month;int _day;
};ostream& operator<<(ostream& out, const Date& d);
istream& operator>>(istream& in, Date& d);

Date.cpp

#include "Date.h"Date::Date(int year, int month, int day)
{_year = year;_month = month;_day = day;if (_year < 1 ||_month < 1 || _month > 12 ||_day < 1 || _day > GetMonthDay(_year, _month)){//assert(false);Print();cout << "日期非法" << endl;}
}void Date::Print() const
{cout << _year << "/" << _month << "/" << _day << endl;
}bool Date::operator==(const Date& y) const
{return _year == y._year&& _month == y._month&& _day == y._day;
}// d1 != d2
bool Date::operator!=(const Date& y) const
{return !(*this == y);
}bool Date::operator>(const Date& y) const
{if (_year > y._year){return true;}else if (_year == y._year && _month > y._month){return true;}else if (_year == y._year && _month == y._month && _day > y._day){return true;}return false;
}bool Date::operator>=(const Date& y) const
{return *this > y || *this == y;
}bool Date::operator<(const Date& y) const
{return !(*this >= y);
}bool Date::operator<=(const Date& y) const
{return !(*this > y);
}int Date::GetMonthDay(int year, int month)
{assert(year >= 1 && month >= 1 && month <= 12);int monthArray[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;return monthArray[month];
}// d1 += 100
Date& Date::operator+=(int day)
{if (day < 0){return *this -= (-day);}_day += day;while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);++_month;if (_month == 13){_year++;_month = 1;}}return *this;
}Date Date::operator+(int day) const
{Date tmp(*this);tmp += day;return tmp;
}Date& Date::operator-=(int day)
{if (day < 0){return *this += (-day);}_day -= day;while (_day <= 0){--_month;if (_month == 0){--_year;_month = 12;}_day += GetMonthDay(_year, _month);}return *this;
}Date Date::operator-(int day) const
{Date tmp(*this);tmp -= day;return tmp;
}// 21:13继续
// ++d1
Date& Date::operator++()
{*this += 1;return *this;
}// d1++
Date Date::operator++(int)
{Date tmp(*this);*this += 1;return tmp;
}Date& Date::operator--()
{*this -= 1;return *this;
}Date Date::operator--(int)
{Date tmp(*this);*this -= 1;return tmp;
}// d1 - d2
int Date::operator-(const Date& d) const
{// 假设左大右小int flag = 1;Date max = *this;Date min = d;// 假设错了,左小右大if (*this < d){max = d;min = *this;flag = -1;}int n = 0;while (min != max){++min;++n;}return n * flag;
}ostream& operator<<(ostream& out, const Date& d)
{out << d._year << "年" << d._month << "月" << d._day << "日" << endl;return out;
}istream& operator>>(istream& in, Date& d)
{in >> d._year >> d._month >> d._day;return in;
}

test.cpp

#include "Date.h"//void TestDate1()
//{
//	Date d1(2023, 10, 1);
//	Date d2(2023, 11, 3);
//	d1.Print();
//
//	cout << d1 << d2 << endl;
//	
//
//	cin >> d1 >> d2;
//	cout << d1 << d2 << endl;
//
//	int i = 0;
//	i << 10;
//
//	/*double d = 1.1;
//	int i = 2;
//
//	cout << i;
//	cout << d;*/
//}
//int main()
//{
//	TestDate1();
//	return 0;
//}int main()
{// const对象和非const对象都可以调用const成员函数const Date d1(2025, 10, 31);//d1.Print();Date d2(2025, 1, 1);//d2.Print();cout << &d1 << endl;cout << &d2 << endl;return 0;
}

相关文章:

类与对象(中)

类的6个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。 空类中真的什么都没有吗&#xff1f;并不是&#xff0c;任何类在什么都不写时&#xff0c;编译器会自动生成以下 6 个默认成员函数。默认成员函数&#xff1a;用户没有显式实现&#xff0c;编译器会生…...

如何移植ftp服务器到arm板子?

很多厂家提供的sdk&#xff0c;一般都不自带ftp服务器功能&#xff0c; 需要要发人员自己移植ftp服务器程序。 本文手把手教大家如何移植ftp server到arm板子。 环境 sdk&#xff1a;复旦微 Buildroot 2018.02.31. 解压 $ mkdir ~/vsftpd $ cp vsftpd-3.0.2.tar.gz ~/vs…...

npm常见报错整理

npm install时报UNMET PEER DEPENDENCY 现象 npm install时报UNMET PEER DEPENDENCY,且执行npm install好几遍仍报这个。 原因 不是真的缺少某个包,而是安装的依赖版本不对,警告你应该安装某一个版本。 真的缺少某个包。 解决 看了下package.json文件,我的react是有的…...

苍穹外卖—订单模块

该模块分为地址表的增删改查、用户下单、订单支付三个部分。 第一部分地址表的增删改查无非就是对于单表的增删改查&#xff0c;较基础&#xff0c;因此直接导入代码。 地址表 一个用户可以有多个地址&#xff0c;同时有一个地址为默认地址。用户还可为地址添加例如&q…...

MQ的可靠消息投递机制

确保消息在发送、传递和消费过程中不会丢失、重复消费或错乱。 1. 消息的可靠投递 消息持久化&#xff1a; 消息被发送到队列后会存储在磁盘上&#xff0c;即使消息队列崩溃&#xff0c;消息也不会丢失。例如&#xff1a;Kafka、RabbitMQ等都支持持久化消息。Kafka通过将消息存…...

视频多模态模型——视频版ViT

大家好&#xff0c;这里是好评笔记&#xff0c;公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本文详细解读多模态论文《ViViT: A Video Vision Transformer》&#xff0c;2021由google 提出用于视频处理的视觉 Transformer 模型&#xff0c;在视频多模态领域有…...

w179基于Java Web的流浪宠物管理系统的设计与实现

&#x1f64a;作者简介&#xff1a;多年一线开发工作经验&#xff0c;原创团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339;赠送计算机毕业设计600个选题excel文…...

MyBatis框架基础学习(1)

目录 一、MyBatis框架介绍。 &#xff08;1&#xff09;简化开发。 &#xff08;2&#xff09;持久层&#xff1f; &#xff08;3&#xff09;框架的解释&#xff01; 二、JDBC开发缺点。 &#xff08;1&#xff09;硬编码。 &#xff08;2&#xff09;操作繁琐。 三、MyBatis框…...

arm-linux平台、rk3288 SDL移植

一、所需环境资源 1、arm-linux交叉编译器&#xff0c;这里使用的是gcc-linaro-6.3.1 2、linux交叉编译环境&#xff0c;这里使用的是Ubuntu 20.04 3、sdl2源码 https://github.com/libsdl-org/SDL/archive/refs/tags/release-2.30.11.tar.gz 二、代码编译 1、解压sdl2源码…...

51单片机入门_01_单片机(MCU)概述(使用STC89C52芯片)

文章目录 1. 什么是单片机1.1 微型计算机的组成1.2 微型计算机的应用形态1.3 单板微型计算机1.4 单片机(MCU)1.4.1 单片机内部结构1.4.2 单片机应用系统的组成 1.5 80C51单片机系列1.5.1 STC公司的51单片机1.5.1 STC公司单片机的命名规则 2. 单片机的特点及应用领域2.1 单片机的…...

基础项目——扫雷(c++)

目录 前言一、环境配置二、基础框架三、关闭事件四、资源加载五、初始地图六、常量定义七、地图随机八、点击排雷九、格子类化十、 地图类化十一、 接口优化十二、 文件拆分十三、游戏重开 前言 各位小伙伴们&#xff0c;这期我们一起学习出贪吃蛇以外另一个基础的项目——扫雷…...

docker安装elk6.7.1-搜集java日志

docker安装elk6.7.1-搜集java日志 如果对运维课程感兴趣&#xff0c;可以在b站上、A站或csdn上搜索我的账号&#xff1a; 运维实战课程&#xff0c;可以关注我&#xff0c;学习更多免费的运维实战技术视频 0.规划 192.168.171.130 tomcat日志filebeat 192.168.171.131 …...

自然语言处理(NLP)入门:基础概念与应用场景

什么是自然语言处理&#xff08;NLP&#xff09;&#xff1f; 自然语言处理&#xff08;Natural Language Processing, NLP&#xff09;是人工智能&#xff08;AI&#xff09;的一个重要分支&#xff0c;研究如何让计算机理解、生成、分析和与人类语言进行交互。换句话说&…...

AI News(1/21/2025):OpenAI 安全疏忽:ChatGPT漏洞引发DDoS风险/OpenAI 代理工具即将发布

1、OpenAI 的安全疏忽&#xff1a;ChatGPT API 漏洞引发DDoS风险 德国安全研究员 Benjamin Flesch 发现了一个严重的安全漏洞&#xff1a;攻击者可以通过向 ChatGPT API 发送一个 HTTP 请求&#xff0c;利用 ChatGPT 的爬虫对目标网站发起 DDoS 攻击。该漏洞源于 OpenAI 在处理…...

Linux——包源管理工具

一、概要 Linux下的包/源管理命令&#xff1a;主要任务就是完成在Linux环境下的安装/卸载/维护软件。 1.rpm 是最基础的rpm包的安装命令&#xff0c;需要提前下载相关安装包和依赖包。 2.yum/dnf &#xff08;最好用&#xff09;是基于rpm包的自动安装命令&#xff0c;可以自动…...

C++解决走迷宫问题:DFS、BFS算法应用

文章目录 思路:DFSBFSBFS和DFS的特点BFS 与 DFS 的区别BFS 的优点BFS 时间复杂度深度优先搜索(DFS)的优点深度优先搜索(DFS)的时间复杂度解释:空间复杂度总结:例如下面的迷宫: // 迷宫的表示:0表示可以走,1表示障碍 vector<vector<int>> maze = {{0, 0,…...

机器学习09-Pytorch功能拆解

机器学习09-Pytorch功能拆解 我个人是Java程序员&#xff0c;关于Python代码的使用过程中的相关代码事项&#xff0c;在此进行记录 文章目录 机器学习09-Pytorch功能拆解1-核心逻辑脉络2-个人备注3-Pytorch软件包拆解1-Python有参和无参构造构造方法的基本语法示例解释注意事项…...

BLE透传方案,IoT短距无线通信的“中坚力量”

在物联网&#xff08;IoT&#xff09;短距无线通信生态系统中&#xff0c;低功耗蓝牙&#xff08;BLE&#xff09;数据透传是一种无需任何网络或基础设施即可完成双向通信的技术。其主要通过简单操作串口的方式进行无线数据传输&#xff0c;最高能满足2Mbps的数据传输速率&…...

Linux 中的poll、select和epoll有什么区别?

poll 和 select 是Linux 系统中用于多路复用 I/O 的系统调用&#xff0c;它们允许一个程序同时监视多个文件描述符&#xff0c;以便在任何一个文件描述符准备好进行 I/O 操作时得到通知。 一、select select 是一种较早的 I/O 多路复用机制&#xff0c;具有以下特点&#xff…...

单片机-STM32 WIFI模块--ESP8266 (十二)

1.WIFI模块--ESP8266 名字由来&#xff1a; Wi-Fi这个术语被人们普遍误以为是指无线保真&#xff08;Wireless Fidelity&#xff09;&#xff0c;并且即便是Wi-Fi联盟本身也经常在新闻稿和文件中使用“Wireless Fidelity”这个词&#xff0c;Wi-Fi还出现在ITAA的一个论文中。…...

linux日志排查相关命令

实时查看日志 tail -f -n 100 文件名 -f:实时查看 -n:查看多少行 直接查看日志文件 .log文件 cat 文件名 .gz文件 zgcat 文件名 在日志文件搜索指定内容 .log文件 grep -A 3 “呀1” 文件名 -A&#xff1a;向后查看 3&#xff1a;向后查看行数 “呀1”&#xff1a;搜…...

每日一题-二叉搜索树与双向链表

将二叉搜索树转化为排序双向链表 问题描述 输入一棵二叉搜索树&#xff0c;将该二叉搜索树转换成一个排序的双向链表&#xff0c;要求空间复杂度为 O(1)&#xff0c;时间复杂度为 O(n)&#xff0c;并且不能创建新的结点&#xff0c;只能调整树中结点的指针指向。 数据范围 …...

【多视图学习】Self-Weighted Contrastive Fusion for Deep Multi-View Clustering

Self-Weighted Contrastive Fusion for Deep Multi-View Clustering 用于深度多视图聚类的自加权对比融合 TMM 2024 代码链接 论文链接 0.摘要 多视图聚类可以从多个视图中探索共识信息&#xff0c;在过去二十年中越来越受到关注。然而&#xff0c;现有的工作面临两个主要挑…...

ASK-HAR:多尺度特征提取的深度学习模型

一、探索多尺度特征提取方法 在近年来&#xff0c;随着智能家居智能系统和传感技术的快速发展&#xff0c;人类活动识别&#xff08;HAR&#xff09;技术已经成为一个备受瞩目的研究领域。HAR技术的核心在于通过各种跟踪设备和测量手段&#xff0c;如传感器和摄像头&#xff0…...

C语言:数据的存储

本文重点&#xff1a; 1. 数据类型详细介绍 2. 整形在内存中的存储&#xff1a;原码、反码、补码 3. 大小端字节序介绍及判断 4. 浮点型在内存中的存储解析 数据类型结构的介绍&#xff1a; 类型的基本归类&#xff1a; 整型家族 浮点家族 构造类型&#xff1a; 指针类型&…...

深入理解动态规划(dp)--(提前要对dfs有了解)

前言&#xff1a;对于动态规划&#xff1a;该算法思维是在dfs基础上演化发展来的&#xff0c;所以我不想讲的是看到一个题怎样直接用动态规划来解决&#xff0c;而是说先用dfs搜索&#xff0c;一步步优化&#xff0c;这个过程叫做动态规划。&#xff08;该文章教你怎样一步步的…...

单片机基础模块学习——数码管(二)

一、数码管模块代码 这部分包括将数码管想要显示的字符转换成对应段码的函数&#xff0c;另外还包括数码管显示函数 值得注意的是对于小数点和不显示部分的处理方式 由于小数点没有单独占一位&#xff0c;所以这里用到了两个变量i,j用于跳过小数点导致的占据其他字符显示在数…...

【大数据】机器学习----------强化学习机器学习阶段尾声

一、强化学习的基本概念 注&#xff1a; 圈图与折线图引用知乎博主斜杠青年 1. 任务与奖赏 任务&#xff1a;强化学习的目标是让智能体&#xff08;agent&#xff09;在一个环境&#xff08;environment&#xff09;中采取一系列行动&#xff08;actions&#xff09;以完成一个…...

flink写parquet解决timestamp时间格式字段问题

背景 Apache Parquet 是一种开源的列式数据文件格式,旨在实现高效的数据存储和检索。它提供高性能压缩和编码方案(encoding schemes)来批量处理复杂数据,并且受到许多编程语言和分析工具的支持。 在我们通过flink写入parquet文件的时候,会遇到timestamp时间格式写入的问题。…...

redis实现lamp架构缓存

redis服务器环境下mysql实现lamp架构缓存 ip角色环境192.168.242.49缓存服务器Redis2.2.7192.168.242.50mysql服务器mysql192.168.242.51web端php ***默认已安装好redis&#xff0c;mysql 三台服务器时间同步&#xff08;非常重要&#xff09; # 下载ntpdate yum -y install…...