类和对象 - 中
本文已收录至《C++语言》专栏!
作者:ARMCSKGT
目录
前言
正文
构造函数
对比C和C++的初始化
构造函数的使用与特性
默认构造函数
C++11关于默认构造缺陷的补丁
析构函数
析构函数特性
默认析构和自定义析构
拷贝构造函数
问题聚焦
拷贝构造的定义和特性
使用场景
构造函数小结
运算符重载
定义方式
特性
使用说明
运算符重载原理
赋值运算符重载
前后置++和--
const修饰this
取地址重载和const取地址重载
最后
前言
C++类在设计之时,规定类中有六个默认的成员函数,这些成员函数天生就存在,而且功能都很强大,类和对象的关键点就在这六个默认成员函数的学习,本篇将会逐一介绍这六个成员函数,让我们向类和对象的深处出发!
正文
C++规定在每个类中有六个默认函数成员:
函数 功能 重要性 构造函数 定义和初始化成员变量 重要 析构函数 释放申请的内存空间(销毁成员变量) 重要 拷贝构造(函数) 实现对象间的深拷贝 重要 赋值重载(函数) 实现对象间的深赋值 重要 取地址重载(函数) 自定义类对象取地址操作符功能 一般 const取地址重载(函数) 自定义对象取地址操作符功能const修饰返回的地址 一般 这些函数我们不写,编译器也会自己写一个默认的函数代替对应函数!
//以日期类的方式初见六大默认成员函数
class Date
{
public://构造函数Date(size_t year = 1970, size_t month = 1, size_t day = 1){_year = year;_month = month;_day = day;}//析构函数~Date(){_year = 0;_month = 0;_day = 0;}//拷贝构造函数(简称:拷贝构造)Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}//赋值重载函数(赋值运算符重载)Date& operator=(const Date& d){_year = d._year;_month = d._month;_day = d._day;return *this;}//取地址运算符重载Date* operator&(){return this;}//const返回取地址运算符重载,const修饰thisconst Date* operator&() const{return this;}private:size_t _year;size_t _month;size_t _day;};
构造函数
对比C和C++的初始化
我们在使用C语言实现一些例如顺序表,栈等简单数据结构时,一般都会写一个初始化函数Init,防止野指针访问,但这样很容易让我们忘记去调用!
在C++中,为了避免这种事情,引入了构造函数,在对象实例化时编译器自动调用构造函数进行初始化,所以构造函数是为对象自动初始化而生的!
我们以日期对象为例,对比C与C++的初始化方案:
//C语言实现日期功能 typedef struct C_Date //日期数据结构体 {size_t _year;size_t _month;size_t _day; }C_Date;void InitDate(C_Date* L)//初始化函数 {L->_year = 0;L->_month = 0;L->_day = 0; }
//C++实现日期类 class CPP_Date //日期对象 { public://默认构造CPP_Date(size_t year){_year = year;_month = 1;_day = 1;}//重载实现多种默认构造方式CPP_Date(size_t year, size_t month, size_t day){_year = year;_month = month;_day = day;}private:size_t _year;size_t _month;size_t _day; };
可以发现C++中类融入构造函数后只需要实例化对象就能同时完成初始化,非常方便!而且结合C++的缺少参数,函数重载等新特性,可以让初始化丰富多样,增强程序可用性!
对比C与C++,可以发现C++非常贴心,就像汽车中的手动挡与自动挡,但两者在不同场合各有千秋,在程序开发上C++的更胜一筹,在较为底层且需要更细节的程序控制时C语言更胜一筹!不过一般在程序开发中,C与C++可以搭配一起编程!
构造函数的使用与特性
构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,以保证每个数据成员都有 一个合适的初始值,并且在对象整个生命周期内只调用一次(实例化时被编译器调用)。
构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并不是开空间创建对象,而是初始化对象成员变量。
构造函数的定义方式:
class Test { public: //构造函数必须公开Test(参数) {} //构造函数的函数名与类名相同且没有返回值 };
构造函数的特性
- 函数名与类名相同。
- 无返回值(不需要写返回值类型,void也不需要写)。
- 对象实例化时编译器自动调用对应的构造函数。
- 构造函数可以重载,支持多个构造函数,但是默认的构造函数只有一个。
使用构造函数初始化日期对象:
//C++实现日期类 class CPP_Date //日期对象 { public://默认构造函数只允许出现一种显示,如果定义全缺省就可以代替默认构造了//CPP_Date()//默认构造函数初始化-功能比较局限//{// _year = 0;// _month = 0;// _day = 0;//}//构造函数可以重载实现多种构造方式CPP_Date(size_t year){_year = year;_month = 1;_day = 1;}//一般使用全缺省值方式代替默认构造-智能方便CPP_Date(size_t year = 1970, size_t month = 1, size_t day = 1){_year = year;_month = month;_day = day;}private:size_t _year;size_t _month;size_t _day; };int main() {//CPP_Date d(); //注意:这种调用默认构造的方式是错误的,调用默认构造不需要加()CPP_Date d1;CPP_Date d2(2022);CPP_Date d3(2023,3,12);//可以通过调用不同的构造函数实例化多个不同的对象 }
默认构造函数
如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦
用户显式定义编译器将不再生成。那有人可能会问,既然编译器会自动生成构造函数,我们为什么还要去写?
注意:编译器生成的默认构造函数,对内置类型不做处理,对自定义类型会调用该对象的构造函数!
数据类型区分
- 内置类型:int,char,double等。
- 自定义类型:struct,class等,这些自定义类型可以有自己的默认构造函数。
编译器默认构造对内置类型的初始化:
编译器默认构造初始化内置类型 自定义默认构造:
//C++实现日期类 class CPP_Date //日期对象 { public://无参构造函数//CPP_Date()//{// _year = 0;// _month = 0;// _day = 0;//}//全缺省默认构造CPP_Date(size_t year = 1970, size_t month = 1, size_t day = 1){_year = year;_month = month;_day = day;}//当存在两种实例化相同的构造方法时,只能存在一种,否则在调用时会出错!//例如 (CPP_Date d;) 编译器无法判断d对象调用的是哪一个构造函数private:size_t _year;size_t _month;size_t _day; };
自定义默认构造完成内置类型的初始化
无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。
注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数。C++11关于默认构造缺陷的补丁
为了解决内置类型无法被编译器生成的默认构造初始化的问题,在C++11中支持内置类型在声明阶段给缺省值,当编译器生成默认构造函数时,使用这些缺省值初始化内置类型。
class CPP_Date //日期对象 { public:private:size_t _year = 1970; //声明阶段赋予缺省值size_t _month = 1;size_t _day = 1;//注意:类成员变量定义在构造函数的初始化列表,并不是在声明阶段! };
所以,对于内置类型要么自定义默认构造函数,或者在声明时赋予缺省值,对于自定义类型编译器会调用对应的构造函数!
析构函数
我们在写顺序表时,在结束使用时需要调用销毁函数是否内存空间,但是我们可能经常也会忘记释放空间,析构函数就是用来销毁对象和释放空间的!
析构函数是特殊的成员函数,其功能与构造函数相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时(生命周期结束时)会自动调用析构函数,完成对象中资源的清理工作。
析构函数特性
- 析构函数名是在类名前加上字符 ~。
- 无参数无返回值类型(void也不需要写)。
- 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。
- 析构函数不能重载。
- 对象生命周期结束时,C++编译系统系统自动调用析构函数。
对于析构函数,最大的特性是在对象生命周期结束时被自动调用,与构造函数的区别在于不支持重载,也就是说一个对象只能有一个析构函数!
默认析构和自定义析构
如果我们不写析构函数,编译器也会默认生成,但编译器生成的析构函数对内置类型仍然不做处理,对自定义类型会调用对应的析构函数处理!
//析构函数定义 class Test {~Test() {//释放方法} };
//简易栈对象 typedef int DataType; class Stack { public:Stack(size_t capacity = 3){_array = (DataType*)malloc(sizeof(DataType) * capacity);if (NULL == _array){perror("malloc申请空间失败!!!");return;}_capacity = capacity;_size = 0;cout << "构造函数初始化栈对象" << endl;}void Push(DataType data){// CheckCapacity();_array[_size] = data;_size++;}// 其他方法...~Stack(){if (_array){free(_array);_array = NULL;_capacity = 0;_size = 0;}cout << "析构函数释放栈对象空间" << endl;} private:DataType* _array;int _capacity;int _size; };
对于自定义类型和内置类型,是否存在析构函数进行释放影响都不大,当涉及我们自己动态开辟空间时,就需要使用析构函数释放空间!
注意:创建哪个类的对象则调用该类的析构函数,销毁那个类的对象则调用该类的析构函数!对于析构函数,只要是对象中涉及动态内存申请,则需要使用析构函数释放!
拷贝构造函数
拷贝构造也是构造函数的一种,但是参数不同则构成重载,功能和特性与构造函数不同!
问题聚焦
我们在创建对象时,如果需要拷贝一个一模一样的对象,也就是复制一个对象;那么就需要创建一个一模一样的对象后将数据拷贝一份过去。
编译器默认生成的拷贝构造函数只支持浅拷贝,也就是值拷贝,对于内置类型,浅拷贝是没有影响的,但是如果对象中申请了空间,那么该对象中必定有一个指针指向该空间的首地址,浅拷贝只会讲该地址拷贝一份给另一个对象,那么会导致一个严重的问题,就是两个对象申请的空间是同一个地址,在增删查改和析构时拷贝的对象析构函数会对同一片空间进行修改和重复释放一片空间导致异常,最后成为野指针问题!
浅拷贝只是简单的逐字节拷贝,对于对象内部有空间申请的,会发生共用空间重复析构的情况;而深拷贝是在新对象中开辟一块属于自己的新空间,然后将数据逐一拷贝过来,新旧对象之间的数据相互独立!
浅拷贝下对象共用一块空间
拷贝构造的定义和特性
拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。
特性
- 拷贝构造函数是构造函数的一个重载形式。
- 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。
定义和调用
class Test {//拷贝构造形参的定义方式是唯一的:(const 类型& )Test(const Test& T) {//拷贝方法} //定义方式 };int main() {Test t1;Test t2(t1); //调用拷贝构造方式一Test t3 = t2; //调用拷贝构造方式二return 0; }
定义须知
- 编译器默认生成的拷贝构造,只是简单拷贝,只能用于非动态内存开辟的空间
- 拷贝构造的参数定义方式是唯一的
- 拷贝构造函数函数名与构造函数相同,不过参数类型为类对象的引用,不加引用则会发生无穷拷贝(因为形参是拷贝而来的,这样形参会陷入无限递归拷贝形参)
形参无穷递归拷贝 使用场景
//日期类示例 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); //拷贝构造方式一Date d3 = d2; //拷贝构造方式二return 0; }
像日期类这样没有动态内存申请的对象,使用编译器默认生成的拷贝构造进行浅拷贝即可,但是向数据结构需要动态内存申请等相对复杂的对象,就需要自定义拷贝构造实现深拷贝!
拷贝构造函数典型调用场景
- 使用已存在对象创建新对象
- 函数参数类型为类类型对象
- 函数返回值类型为类类型对象
说明
- 对于深拷贝,是有一定代价的,为了提高程序效率,一般对象传参时,尽量使用引用类型,返回时根据实际场景,能用引用尽量使用引用!
- 默认拷贝构造函数与默认构造函数名相同,当我们只写拷贝而不写构造时,编译器就会报错,因为此时的拷贝会被误以为是默认构造函数也就是说,默认拷贝构造函数存在的前提是默认构造函数已存在。
构造函数小结
构造大家族到这里基本内容就介绍的差不多了!
类型 用途 处理情况 构造函数 初始化对象 不对内置类型作处理,自定义类型调用对应构造函数 析构函数 销毁对象 也不对内置类型作处理,自定义类型调用对应析构函数 拷贝构造函数 拷贝对象 只能对简单内置类型做处理,自定义类型需要自己实现深拷贝
运算符重载
C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
运算符重载的引入,主要是为了解决基本运算符功能不足以满足自定义类型需求的情况,例如日期类的加减,以及前后置++和--等,需要自定义对象运算符的功能!
定义方式
返回值类型 operator操作符(参数) {//自定义操作符功能 }// operator 是运算符重载的关键字
特性
不能通过连接其他符号来创建新的操作符:比如operator@
重载操作符必须有一个类类型参数
用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
作为类成员函数重载时,其形参看起来比操作数数目少一个,因为成员函数的第一个参数为隐藏的this
对于内置运算符,不能改变其含义
operator操作符 就是函数名
注意这5个运算符不能重载:(1) .* ,(2) :: ,(3)sizeof,(4)?:,(5) .
//日期类 class Date { public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}//为了保证封装性,类成员变量一般是私有,所以运算符重载一般定义在类内部bool operator==(const Date& d){//这里相当于 *this 与 d 的 == 比较return _year == d._year&& _month == d._month&& _day == d._day;}private:int _year;int _month;int _day; };int main() {Date d1(2018, 9, 26);Date d2(2018, 9, 27);cout << (d1 == d2) << endl; //这里相当于调用 d1.operator==(d2)return 0; }
使用说明
- operator 函数中的操作数取决于参数个数
- operator 一般定义在类中,方便访问类成员,当定义在类中时,运算符左边的对象默认是*this
- operator 如果定义在类外,则无法访问类的所有成员,此时要么在类中定义特定函数获取私有成员要么声明为友元函数,但是大部分场景下都没有定义在类中更合适
运算符重载原理
运算符重载的原理与函数重载原理基本相同,也是对函数名修饰。
如果定义在类中在Linux环境下修饰规则为:_ZN4D+类名+运算符英文简称+ERKS_
赋值运算符重载
通过上面的铺垫,我们就要介绍下一个默认成员,那就是赋值重载函数!
class Test {};
赋值重载是将一个对象赋值給另一个对象,与拷贝构造相似,但是拷贝构造是通过一个对象去实例化一个相同的对象,而赋值重载的前提是两个对象已经实例化存在,相互之间再赋值!本质区别在于:一个是对象尚未实例化,另一个是两个对象都已存在!当两个对象都被创建,并发生赋值行为时,才叫做赋值重载!
对于这种自定义类型复制的问题,就会涉及深拷贝和浅拷贝的问题,所以赋值重载是很有必要的!
//日期类 class Date { public:Date(int year = 1900, int month = 1, int day = 1){_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; //返回赋值的对象的引用(也就是自己)//这里之所以返回自己的引用是因为会发生 d1 = d2 = d3 这样连等的情况//使用引用可以有效避免拷贝}private:int _year;int _month;int _day; };
赋值运算符重载格式
- 参数类型:const T&,传递引用可以提高传参效率
- 返回值类型:T&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值
- 检测是否自己给自己赋值
- 返回*this :要复合连续赋值的含义
- 赋值运算符只能重载成类的成员函数不能重载成全局函数
如果赋值运算符重载成全局函数,就没有this指针了,需要给两个参数,而且此时编译器就会报错error C2801: “operator =”必须是非静态成员!
原因:赋值运算符如果不显式实现,编译器会生成一个默认的。此时用户再在类外自己实现一个全局的赋值运算符重载,就和编译器在类中生成的默认赋值运算符重载冲突了,故赋值运算符重载只能是类的成员函数。
默认赋值重载函数:用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝。
注意:内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符重载完成赋值。
所以赋值重载的使用环境与拷贝构造类似:如果类中未涉及到动态内存申请(资源管理),赋值运算符是否实现都可以;一旦涉及到资源管理则必须要实现!
//栈对象 - 猜猜是否会发生与拷贝构造相同的问题 typedef int DataType; class Stack { public:Stack(size_t capacity = 10){_array = (DataType*)malloc(capacity * sizeof(DataType));if (nullptr == _array){perror("malloc申请空间失败");return;}_size = 0;_capacity = capacity;}void Push(const DataType& data){// CheckCapacity();_array[_size] = data;_size++;}~Stack(){if (_array){free(_array);_array = nullptr;_capacity = 0;_size = 0;}} private:DataType* _array;size_t _size;size_t _capacity; };int main() {Stack s1;s1.Push(1);s1.Push(2);s1.Push(3);s1.Push(4);Stack s2;s2 = s1;return 0; }
前后置++和--
对于自定义对象,前后置++和--还是经常会使用到的!
class Test {Test& operator++() {} //前置++Test operator++(int) {} //后置++Test& operator--() {} //前置--Test operator--(int) {} //后置-- };
//以日期类进行介绍 class Date { public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}// 前置++:返回+1之后的结果 // 注意:this指向的对象函数结束后不会销毁,故以引用方式返回提高效率Date& operator++(){_day += 1;return *this;}// 后置++: // 注意:后置++是自己+1然后返回+1之前的值 // 而temp是临时对象,因此只能以值的方式返回,不能返回引用Date operator++(int){Date temp(*this);_day += 1;return temp;} private:int _year;int _month;int _day; };int main() {Date d1;d1++;++d1;return 0; }
原理:前置++和后置++都是一元运算符,为了让前置++与后置++形成能正确重载,C++规定:后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器自动传递(前后置--实现与++相同)。
const修饰this
将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。
const常被用来修饰引用和指针,使用const修饰可以提高程序的健壮性!
使用场景
- 被(指针)指向对象是常亮或临时变量
- 被引用对象是常亮或临时变量
这些对象必须使用const修饰,避免权限放大的问题!
修饰this指针格式
有小伙伴可能会疑惑,this指针我们不能显示定义,那么如果要const修饰怎么办?
对于this指针的修饰,格式为:
class Test {void Fun() const //将const加在函数参数后即可{//函数方法} };
//设想以下日期类代码的运行结果 class Date { public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << "Print()" << endl;cout << "year:" << _year << endl;cout << "month:" << _month << endl;cout << "day:" << _day << endl << endl;}void Print() const{cout << "Print()const" << endl;cout << "year:" << _year << endl;cout << "month:" << _month << endl;cout << "day:" << _day << endl << endl;} private:int _year; // 年int _month; // 月int _day; // 日 };int main() {Date d1(2022, 1, 13);d1.Print();const Date d2(2022, 1, 13);d2.Print();return 0; }
代码运行结果 总之,const修饰this指针可以起到权限平移的作用!
取地址重载和const取地址重载
这两个默认成员函数一般不用重新定义 ,编译器默认会生成。
class Date { public:Date* operator&() //返回对象的地址{return this;}const Date* operator&() const //返回const修饰对象的地址{return this;} private:int _year; // 年int _month; // 月int _day; // 日 };
这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需要重载,比如想让别人获取到指定的内容!
最后
以上就是 类和对象 - 中 的全部内容了,本篇介绍了类的六大默认成员函数,对于构造函数何时用编译器自动生成的,何时自己实现都需要依照情况而定!对于每个成员其规则和细节都很多,需要我们在长期的使用中去牢固的掌握,掌握了这六大成员函数的使用,那么你将对类和对象的掌握又进一步!
本次 <C++类和对象 - 中> 就介绍到这里啦,希望能够尽可能帮助到大家。
如果文章中有瑕疵,还请各位大佬细心点评和留言,我将立即修补错误,谢谢!
🌟其他文章阅读推荐🌟
C++ 类和对象 - 上
C++ 入门知识
数据结构初阶 <栈>
🌹欢迎读者多多浏览多多支持!🌹
相关文章:

类和对象 - 中
本文已收录至《C语言》专栏! 作者:ARMCSKGT 目录 前言 正文 构造函数 对比C和C的初始化 构造函数的使用与特性 默认构造函数 C11关于默认构造缺陷的补丁 析构函数 析构函数特性 默认析构和自定义析构 拷贝构造函数 问题聚焦 拷贝构造的定…...

Android之屏幕适配方案
在说明适配方案之前,我们需要对如下几个概念有所了解:屏幕尺寸,屏幕分辨率,屏幕像素密度。 屏幕尺寸 屏幕尺寸指屏幕的对角线的物理长度,单位是英寸,1英寸2.54厘米。 比如常见的屏幕尺寸:5.0、5…...

SpringBoot+jersey跨域文件上传
一、配置tomcat服务器 1.1、添加upload文件夹 在webapps\Root文件夹下创建用于接收上传文件的upload文件夹 1.2、修改conf\web.xml设置允许上传文件 <init-param><param-name>readonly</param-name><param-value>false</param-value></ini…...

数据结构One——绪论
本喵是FW视频封面最终版宝子,你不点个赞吗?不评个论吗?不收个藏吗? 最后的最后,关注我,关注我,关注我,你会看到更多有趣的博客哦!!! 喵喵喵&#…...

JVM篇之内存及GC
目录一、JVM内存区域1.1程序计数器1.2虚拟机栈1.3本地方法栈1.4堆1.5方法区二、JVM运行时内存2.1新生代(轻量级GC)2.2老年代(重量级GC)一、JVM内存区域 JVM 内存区域主要分为线程私有区域【程序计数器、虚拟机栈、本地方法栈】、线程共享区域【JAVA 堆、…...

Linux驱动操作地址(寄存器)的一些方式
Linux驱动操作地址(寄存器)的一些方式 文章目录Linux驱动操作地址(寄存器)的一些方式1.对绝对地址赋值操作2. ioremap2.1 void __iomem *地址2.2 volatile unsigned int *地址2.3 structioremap1.对绝对地址赋值操作 对绝对地址0x100000赋值操作 *&…...

Java日志框架介绍
Log4j Apache Log4j是一个基于Java的日志记录工具。它是由Ceki Glc首创的,现在则是Apache软件基金会的一个项目。 Log4j是几种Java日志框架之一。 Log4j 2 Apache Log4j 2是apache开发的一款Log4j的升级产品。 Commons Logging Apache基金会所属的项目,是…...

编程中遇到的计算机大小端概念
概念大小端(Endian)是指在一个多字节的数据中,字节的存储顺序的规定。通俗来说,就是指数据在计算机内部存储时的顺序问题。在计算机系统中,一个数据项可能占据多个存储单元。在这种情况下,这个数据项的存储…...

日志与可视化方案:从ELK到EFK,再到ClickHouse
EFK方案 从ELK谈起 ELK是三个开源软件的缩写,分别表示:Elasticsearch,Logstash,Kibana。新增了一个FlieBeat,它是一个轻量级的日志收集处理工具,FlieBeat占用资源少,适用于在各个服务器上搜集…...

字符函数和字符串函数(上)——“C”
各位CSDN的uu们你们好呀,今天小雅兰来给大家介绍一个全新的知识点,就是字符函数和字符串函数啦,其实其中有些函数我之前已经学习过了,比如strlen、strcpy;也有一些之前不是很熟悉的函数,比如strstr、strtok…...

九龙证券|下周解禁市值超400亿元,3股解禁压力较大
下周3股解禁比例超50%。 百利电气昨日盘中直线拉升封板,至此,百利电气两连板,累计涨幅20.85%。 昨日晚间,百利电气发布股票交易反常动摇公告称,公司不触及“室温超导”相关业务,也未打开相关研发和投入。公…...

一个大型网站架构的演变历程
正序: Rome was not built in a day(罗马不是一天建成的。)一个成熟的大型网站从来都不是一蹴而就的,需要经过多次架构的调整和升级,我们熟知的大型网站比如京东、淘宝、亚马逊,它们每天都有巨大的用户访问…...

前端前沿web 3d可视化技术 ThreeJS学习全记录
前端前沿web 3d可视化技术 随着浏览器性能和网络带宽的提升 使得3D技术不再是桌面的专利 打破传统平面展示模式 前端方向主要流向的3D图形库包括Three.js和WebGL WebGL灵活高性能,但代码量大,难度大,需要掌握很多底层知识和数学知识 Threej…...

链表经典笔试题(LeetCode刷题)
本篇文章主要是对力扣和牛客网上一些经典的和链表有关的笔试题的总结归纳,希望对你有所帮助。 目录 一、移除链表元素 1.1 问题描述 1.2 思路一 1.2.1 分析 1.2.2 代码 1.3 思路二 1.3.1 分析 1.2.3 思路三 1.3 代码实现 1.3.1 思路1的代码 1.3.2 思路2的…...

SpringCloud五大组件
微服务SpringCloud整合技术组件基本流程: 引入组件启动器依赖坐标覆盖默认配置即application.properties配置文件(每个微服务只有一个并且服务启动默认加载)引导类(微服务入口即main方法)自定义开启组件注解 SpringCloudEureka 服务注册中心,分为Eure…...

Echart的使用初体验,Echarts的基本使用及语法格式,简单图表绘制和使用及图例添加【学习笔记】
Echart? ECharts 是一个使用 JavaScript 实现的开源可视化库,涵盖各行业图表,满足各种需求。 ECharts 遵循 Apache-2.0 开源协议,免费商用。 ECharts 兼容当前绝大部分浏览器(IE8/9/10/11,Chrome…...

聊聊腾讯T13技术专家被开除
这两天腾讯的技术大佬stonehuang被曝离开腾讯,据他老婆在小红书上发的帖子称是遭遇了裁员,说实话刚看到这个消息我挺震惊的,stonehuang在中国大前端领域是排得上号的专家,同时他2005年就加入了腾讯,在qq空间的发展历程…...

c++ 常见宏、模板用法【1】
目录1、宏定义实现简单的断言2、可变参数模板3、变量模板4、宏定义实现范围内的for循环5、模板实现函数对象6、宏定义实现作用域限定7、类型萃取模板1、宏定义实现简单的断言 #define ASSERT(expr) \if(!(expr)) { \std::cout << "assertion failed: " <&l…...

【25】Verilog进阶 - 序列检测
VL25 输入序列连续的序列检测 本题并不难【中等】难度给高了 【做题关键】 (1)需要使用移位寄存器的思路。其实reg型是寄存器,也可以当做是移位寄存器,重要的是对其的处理,使用的是移位寄存器的思路 (2)注意新移入数据存放在低位 1 题目 + 代码 + TestBench 很简单,没…...

如何绕开运营商的 QoS 限制
运营商针对 UDP 进行限制,这是 QUIC 以及类似 UDP-Based 协议的推广阻力之一,上了线很多问题,丢包,慢等的问题严重增加运维,运营成本。 按照运营商五元组 QoS 这种简单粗暴不惹事的原则,只要换一个端口就可…...

C#基础教程22 异常处理
文章目录 C# 异常处理语法C# 中的异常类异常类 描述异常处理创建用户自定义异常C# 异常处理 异常是在程序执行期间出现的问题。C# 中的异常是对程序运行时出现的特殊情况的一种响应,比如尝试除以零。 异常提供了一种把程序控制权从某个部分转移到另一个部分的方式。C# 异常处理…...

java八股文--java基础
java基础1.什么是面向对象,谈谈对面向对象的理解2.JDK JRE JVM的区别与联系3.和equals4.hashCode与equals5.String StringBuffer StringBuilder的区别6.重载和重写的区别7.接口和抽象类8.List和Set的区别9.ArrayList和LinkedList10.HashMap和HashTable的区别&#x…...

2022年全国职业院校技能大赛(中职组)网络安全竞赛试题A模块第四套解析(详细)
2022年全国职业院校技能大赛(中职组) 网络安全竞赛试题 (4) (总分100分) 赛题说明 一、竞赛项目简介 “网络安全”竞赛共分A.基础设施设置与安全加固;B.网络安全事件响应、数字取证调查和应用安全;C.CTF夺旗-攻击;D.CTF夺旗-防御等四个模块。根据比赛实际情况,竞…...

【Spark】spark使用jdbc连接带有kerberos认证的hive jdbc
背景 这个需求就是spark不通过spark-hive的方式访问hive数据,而是通过spark读取hive jdbc的方式访问hive数据,因为这个hive有kerberos认证,在网上也不是很容易搜索到这样的操作案例。不多bb,直接上教程。 准备工作 准备一个hiv…...

【Maven】项目中pom.xml坐标定义以及pom基本配置
目录 一、pom.xml坐标定义 二、pom 基本配置 一、pom.xml坐标定义 在 pom.xml 中定义坐标,内容包括:groupId、artifactId、version,详细内容如下: <!--项目名称,定义为组织名项目名,类似包名-->&l…...

Linux GCC 编译详解
文章目录一、GCC 编译器简介二、GCC 工作流编程语言的发展GCC 工作流程gcc 和 g 的区别三、使用 GCC 编译GCC 编译格式GCC 编译流程多个源文件编译一、GCC 编译器简介 首先,什么是编译器呢? 我们可以使用编辑器(如 linux 下的 vi、windows 下…...

谁说程序员不懂了浪费,女神节安排
Python的PyQt框架的使用一、前言二、女神节文案三、浪漫的代码四、官宣文案一、前言 个人主页: ζ小菜鸡大家好,我是ζ小菜鸡,特在这个特殊的日子献上此文,希望小伙伴们能讨自己的女神欢心。 二、女神节文案 1.生活一半是柴米油盐,…...

上市公司管理层短视指标(2007-2020)
1、数据说明:将研发⽀出的减少量(∆R&D)作为管理层短视⾏为的度量指标,即∆R&D为公司t年的研发⽀出减去t-1年的研发⽀出并除以t-1年末的总资产再乘以100。2、数据来源:自主整理3、时间跨度:2007-20…...

IDDPM 和 DDIM 对比
IDDPM 和 DDPM 对比IDDPMDDIMIDDPM IDDPM:Improved Denoising diffusion probabilistic models learning Σθ\Sigma_{\theta}Σθ, 即Σθ(xt,t)exp(vlogβt(1−v)logβ~t)\Sigma_{\theta}\left(x_{t}, t\right)\exp \left(v \log \beta_{t}(1…...

链表OJ题(上)
✅每日一练:876. 链表的中间结点 - 力扣(LeetCode) 解题思路: 定义快慢指针,让快指针走2步,慢指针走1步,当fast或者fast.next为空时,走完链表,此时slow就是中间位置 pub…...