【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; //输出0return 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://xiahunao.cn/news/2777202.html

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

相关文章

封装sku组件

1. 准备模板渲染规格数据 使用Vite快速创建一个Vue项目&#xff0c;在项目中添加请求插件axios&#xff0c;然后新增一个SKU组件&#xff0c;在根组件中把它渲染出来&#xff0c;下面是规格内容的基础模板 <script setup> import { onMounted, ref } from vue import axi…

【Java面试】数据类型常见面试题

什么是包装类型 将基本类型包装进了对象中得到的类型 基本类型和包装类型有什么区别 用途不同&#xff1a;基本类型一般用于局部变量&#xff0c;包装类型用于其他地方存储方式不同&#xff1a;用于局部变量的基本类型存在虚拟机栈中的局部变量表中&#xff0c;用于成员变量…

[C/C++] -- Boost库、Muduo库编译安装使用

1.Muduo库 Muduo 是一个基于 C11 的高性能网络库&#xff0c;其核心是事件驱动、非阻塞 I/O、线程池等技术&#xff0c;以实现高并发、高性能的网络通信。Muduo 库主要由陈硕先生开发维护&#xff0c;已经成为 C 服务器程序员的常用工具之一。 Muduo 库的主要特点&#xff1a…

每日OJ题_位运算①_位运算解题方法+3道OJ

目录 位运算算法原理 ①力扣191. 位1的个数 解析代码 ②力扣338. 比特位计数 解析代码 ③力扣461. 汉明距离 解析代码 位运算算法原理 常见位运算解题方法&#xff1a; 1. 基础位运算&#xff1a; &&#xff1a;按位与&#xff0c;有0就是0 | &#xff1a;按位或&a…

横扫Spark之 - 22个常见的转换算子

水善利万物而不争&#xff0c;处众人之所恶&#xff0c;故几于道&#x1f4a6; 文章目录 1. map()2. flatMap()3. filter()4. mapPartitions()5. mapPartitionsWithIndex()6. groupBy()7. distinct()8. coalesce()9. repartition()10. sortBy()11. intersection()12.union()13.…

蓝桥杯每日一练(python)B组

###来源于dotcpp的蓝桥杯真题 题目 2735: 蓝桥杯2022年第十三届决赛真题-取模&#xff08;Python组&#xff09; 给定 n, m &#xff0c;问是否存在两个不同的数 x, y 使得 1 ≤ x < y ≤ m 且 n mod x n mod y 。 输入格式&#xff1a; 输入包含多组独立的询问。 第一…

二维差分---三维差分算法笔记

文章目录 一.二维差分构造差分二维数组二维差分算法状态dp求b[i][j]数组的二维前缀和图解 二.三维前缀和与差分三维前缀和图解:三维差分核心公式图解:模板题 一.二维差分 给定一个原二维数组a[i][j],若要给a[i][j]中以(x1,y1)和(x2,y2)为对角线的子矩阵中每个数都加上一个常数…

绕过系统访问控制

我们研究了最近NSA/CISA 联合网络安全咨询&#xff0c;该咨询涉及这些组织在红/蓝团队演习中发现的首要网络安全问题。在本文中&#xff0c;您将更深入地了解特定问题&#xff0c;包括适用的实际场景&#xff0c;以及可用于限制或克服该问题的缓解策略。这扩展了 NSA/CISA 报告…

C++自幂数判断<GESP C++ 二级>

题目&#xff1a; 代码&#xff1a; #include <iostream> using namespace std; int main() {int m 0;cin >> m;for (int i 0; i < m; i) {int n 0;cin >> n;// 数一下 n 有多少位数&#xff0c;记为 lint t n, l 0;while (t > 0) {t / 10;l;}/…

boot::process::child::wait_until 线程不安全

最近在项目中需要多线程调用子程序。子程序可能工作时间很长&#xff0c;故用 boost::process::child::wait_until 来实现超时功能。 然而&#xff0c;多线程压力测试时&#xff0c;发现有可能导致 core dump。 经查证&#xff0c;是 boost::process::child::wait_until 的一个…

Linux中断编程

大家好&#xff0c;今天给大家介绍Linux中断编程&#xff0c;文章末尾附有分享大家一个资料包&#xff0c;差不多150多G。里面学习内容、面经、项目都比较新也比较全&#xff01;可进群免费领取。 Linux中断编程涉及到操作系统层面的中断处理机制&#xff0c;它是Linux内核与硬…

SPSS基础操作:对数据按照样本观测值进行排序

在整理数据资料或者查看分析结果时&#xff0c;我们通常希望样本观测值能够按照某一变量的大小进行升序或者降序排列&#xff0c;比如我们想按照学生的学习成绩进行排序&#xff0c;按照销售额的大小对各个便利店进行排序等。以本章附带的数据4为例&#xff0c;如果要按照y4体重…

JavaWeb02-MyBatis

目录 一、MyBatis 1.概述 2.JavaEE三层架构简单介绍 &#xff08;1&#xff09;表现层 &#xff08;2&#xff09;业务层 &#xff08;3&#xff09;持久层 3.框架 4.优势 &#xff08;1&#xff09;JDBC的劣势 &#xff08;2&#xff09;MyBatis优化 5.使用 &#…

第六章:纹理贴图

本文是《从0开始图形学》笔记的第六章,介绍模型纹理的实现,涉及到重心坐标的计算方式和作用,本章之后,我们的模型将从单色变成更为丰富的彩色。 纹理贴图数据格式 前面几章我们已经可以将复杂的模型渲染出来了,但是模型还是单色的,这显然是不够的,模型还需要各种各样的…

除夕快乐(前端小烟花)

家人们&#xff0c;新的一年好运常在&#xff0c;愿大家在新的一年里得偿所愿&#xff0c;发财暴富&#xff0c;愿大家找到属于自己的那个公主&#xff0c;下面就给大家展示一下给公主的烟花 前端烟花 新的一年&#xff0c;新的挑战&#xff0c;愿我们不忘初心&#xff0c;砥砺…

【C生万物】数组

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更新的动力❤️ &#x1f64f;小杨水平有…

教你如何生成自己的专属动态龙新年图像 - Python实现摘要

引言 新年将至&#xff0c;为了给大家带来一丝喜庆和神秘的气氛&#xff0c;我决定用Python编写一个生成专属动态龙图像的小程序。通过这个程序&#xff0c;你可以生成一个独一无二的龙图像&#xff0c;并为它添加动态效果&#xff0c;让它在新年的时刻为你带来好运和祝福。 正…

生成式人工智能攻击的一年:2024

趋势科技最近公布了其关于预期最危险威胁的年度研究数据。生成人工智能的广泛可用性和质量将是网络钓鱼攻击和策略发生巨大变化的主要原因。 趋势科技宣布推出“关键可扩展性”&#xff0c;这是著名年度研究的新版本&#xff0c;该研究分析了安全形势并提出了全年将肆虐的网络…

学习Android的第七天

目录 Android EditText 输入框 设置默认提示文本 范例 获得焦点后全选组件内所有文本内容 范例 限制EditText输入类型 android:inputType 值列表 范例 设置最小行&#xff0c;最多行&#xff0c;单行&#xff0c;多行&#xff0c;自动换行 范例 设置文字间隔 范例 …

力扣231. 2 的幂(数学,二分查找,位运算)

Problem: 231. 2 的幂 文章目录 题目描述思路即解法复杂度Code 题目描述 思路即解法 思路1&#xff1a;位运算 1.易验证2的幂为正数&#xff1b; 2.易得2的幂用二进制表示只能有一个位为数字1 3.即将其转换为二进制统计其二进制1的个数 思路2&#xff1a;数学 当给定数n大于1时…