【C++】类与对象 第二篇(构造函数,析构函数,拷贝构造,赋值重载)

目录

类的6个默认成员函数

初始化和清理

1.构造函数

2.析构函数

3.共同点

拷贝复制

1.拷贝构造

使用细节

2.赋值重载

运算符重载

== <= < >= > !=

连续赋值


C++入门 第一篇(C++关键字, 命名空间,C++输入&输出)-CSDN博客

C++入门 第二篇( 引用、内联函数、auto关键字、指针空值nullptr)-CSDN博客

【C++】类与对象 第一篇(class,this)-CSDN博客

类的6个默认成员函数

默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。

初始化和清理

1.构造函数

特征: 构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任 务并不是开空间创建对象,而是初始化对象其特征如下:

  1. 函数名与类名相同。

  2. 无返回值。

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

  4. 构造函数可以重载。

 class Stack{public:Stack(){_a=nullptr;_size=_capacity=0;}​Stack(int n){_a=(int*)malloc(sizeof(int)*n);_size=_capacity=0;}​void Init(int n=4){_a=(int*)malloc(sizeof(int)*n);if (nullptr==_a){perror("malloc is fail");return;}_capacity=n;_size=0;}​void Push(int x){//...a[_size++]=x;}//...void Dstory(){//...}​private:int _a;int _size;int _capacity;};​int main(){Stack st;//无参//Stack st();//有参​st.Push(1);st.Push(2);st.Push(3);st.Push(4);​st.Dstory();​return 0;}

以上述代码为例:

自动调用初始化

注意:调用无参时如:Data d;此处在后面不能➕(),否则编译器会调用有参的。

使用缺省值:

 class Date{public:Date(int year=1,int month=1,int day=1){_year=1;_month=1;_day=1;}​void print(){cout<<_year<<"/"<<_month<<"/"<<_day<<endl;}​private://成员变量int _year;int _month;int _day;};​int main(){//Date d1;Date d2(2077,2,3);d2.print();​return 0;}

2.析构函数

概念: 通过前面构造函数的学习,我们知道一个对象是怎么来的,那一个对象又是怎么没呢的? 析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由 编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作

特性 析构函数是特殊的成员函数,其特征如下:

  1. 析构函数名是在类名前加上字符 ~

  2. 无参数无返回值类型。

  3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构 函数不能重载

  4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。

例子:

 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;}void Push(DataType data){// CheckCapacity();_array[_size] = data;_size++;}// 其他方法...~Stack(){if (_array){free(_array);_array = NULL;_capacity = 0;_size = 0;}}​private:DataType *_array;int _capacity;int _size;};void TestStack(){Stack s;s.Push(1);s.Push(2);}

3.共同点

如果编译过程不写,那编译器会自动生成一个默认的,但是如果我们实现了任意一个,编译器就不会生成了。

若是自动初始化,那为什么这个地方会生成随机值呢?

C++把类型分成内置类型(基本类型)自定义类型。内置类型就是语言提供的数据类 型,如:int/char...,自定义类型就是我们使用class/struct/union等自己定义的类型,看看 下面的程序,就会发现编译器生成默认的构造函数会对自定类型成员_t调用的它的默认成员 函数。

内置类型(基本类型):int/char/double... /任意类型指针 自定义类型:class/structd定义的

默认生成构造函数:

1.内置类型成员不做处理。

2.自定义类型的成员,会去调用它的默认构造(不用传参数的构造)

 private:// 基本类型/内置类型 - 不进初始化int _year;int _month;int _day;

实用场景:

 class Date{public://内置类型成员不做处理void print(){cout<<_year<<"/"<<_month<<"/"<<_day<<endl;}​private:// 基本类型/内置类型 - 不进初始化int _year;int _month;int _day;};​class MyQueue{// 默认生成构造函数,对自定义类型,会调用它的默认构造函数void push(int x);{​}//...Stack _pushST();Stack _popST();};

析构:

默认生成构造函数:

1.内置类型成员不做处理。

2.自定义类型的成员,会去调用它的析构函数

 class MyQueue{// 默认生成析构函数,对自定义类型,会调用它的析构函数void push(int x);{​}Stack _pushST();Stack _popST();};​int main(){//Date d1;Date d1;d1.print();​MyQueue q;​return 0;}

内置类型并不会主动初始化,但可以通过给缺省值进行初始化:

 private://声明位置给缺省值int _year=1;int _month=1;int _day=1;

无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。 注意:无参构造函数全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为 是默认构造函数。

拷贝复制

1.拷贝构造

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

拷贝构造:内置类型,编译器直接拷贝,自定义类型拷贝需要调用拷贝构造

特征

拷贝构造函数也是特殊的成员函数,其特征如下:

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

    为什么自定义类型要用拷贝构造,而内置类型编译器却可以直接拷贝(按字节拷贝)? ​ 因为自定义类型进行拷贝容易出问题:若要拷贝栈,栈的成员变量都是指向相同的空间,若进行拷贝,则会导致两个Stack指向同一个空间,导致原本Stack执行析构函数时被销毁,而复制的那个则指向空,正确的应该是各有各的空间。

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

class Date{public:Date(int year=2077, int month=10, int day=12){_year = year;_month = month;_day = day;}Date(Date d)//这样拷贝会造成无限递归{_year = d.year;_month = d.month;_day = d.day;}​private:int _year;int _month;int _day;};

在拷贝构造函数 Date(Date d) 中,参数 d 是按值传递的,这意味着每次调用拷贝构造函数时都会创建一个新的 Date 对象,并将原始对象 d 复制到新的对象中。然而,在拷贝构造函数内部,对于拷贝构造函数的调用又会传递同样的参数 d,导致不断地递归调用拷贝构造函数,从而产生无限递归。

则可以使用 & ,使其不在重新创建空间并使用原Date对象

Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}

这个拷贝构造函数将创建一个新的 Date 对象,并将原始对象的 _year_month_day 成员变量的值分别拷贝到新对象的相应成员变量中。通过使用对象引用作为参数,我们可以避免无限递归调用拷贝构造函数的问题,并且确保在构造新对象时不会复制整个对象

 
class Date{public:Date(int year = 2077, int month = 10, int day = 12){_year = year;_month = month;_day = day;}​Date(const Date& d)//const是为了防止写反->d._year = _year;加const缩小权限{cout<<"Date(Date& d);"<<endl;_year = d._year;_month = d._month;_day = d._day;}​private:int _year;int _month;int _day;};​int main(){Date d1(2023, 2, 3);//两种拷贝方式Date d2(d1); // 使用拷贝构造函数创建对象 d2,并将 d1 的值拷贝到 d2 中Date d3=d1;​return 0;}

RunCode:

若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按 字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。

深拷贝是指在对象拷贝时,复制所有的数据和资源,使得新对象和原对象完全独立,互不影响。与之相对的是浅拷贝,浅拷贝只复制指针或引用,导致新旧对象共享同一份数据,修改一个可能会影响另一个。深拷贝能够保证对象之间的独立性和数据完整性。

分清楚是不是拷贝构造:

 class Date{public:Date(int year = 2077, int month = 10, int day = 12){_year = year;_month = month;_day = day;}//拷贝构造函数   Date(const Date& d){cout<<"Date(Date& d);"<<endl;_year = d._year;_month = d._month;_day = d._day;}​//构造函数 不是拷贝构造Date(const Date* d){cout<<"Date(Date& d);"<<endl;_year = d._year;_month = d._month;_day = d._day;}private:int _year;int _month;int _day;};​int main(){Date d1(2023, 2, 3);//Date(const Date* d)Date d2(&d1); Date d3=&d1;​return 0;}

拷贝构造函数典型调用场景:

  • 使用已存在对象创建新对象

  • 函数参数类型为类类型对象

  • 函数返回值类型为类类型对象

使用细节

1使用拷贝构造时最好加上const,以防权限的放大

   // 拷贝构造Date(const Date &d){_year = d.year;_month = d.month;_year = d.year;}

2编译器可自动生成但存在问题

本文所用的日期类可以使用自动生成拷贝,但进行拷贝栈时就会出现问题

当进行拷贝时,用值拷贝,导致两个栈指向同一个空间,造成空间互相覆盖 指向同一块空间的问题:1.插入删除数据会互相影响 2.析构两次,程序崩溃

析构是也跟栈一样是后进先出后定义的先析构,故st2先析构,对st2滞空是,并不影响st1,导致野指针。此时浅拷贝行不通,需要进行深拷贝:

代码实现:

class Stack{public:void Push(const int &data){_array[_size] = data;_size++;}​Stack(const Stack &st){_array = (int *)malloc(sizeof(int) * st._capacity);if (nullptr == _array){perror("malloc is fail");exit(-1);}memcpy(_array, st._array, sizeof(int) * st._size);_size = st._size;_capacity = st._capacity;}​~Stack(){if (_array){delete[] _array;_array = nullptr;_capacity = 0;_size = 0;}}​private:int *_array;int _size;int _capacity;};​int main(){Stack st1;st1.Push(1);st1.Push(2);st1.Push(3);​Stack st2(st1);​return 0;}

什么情况下需要事项拷贝构造呢? 自己实现了析构释放空间,就需要实现拷贝构造

 class Stack{public://构造函数  Stack(size_t _capacity = 10){cout << "Stack(size_t _capacity)" << endl;_array = (int *)malloc(sizeof(int) * _capacity);if (nullptr == _array){perror("malloc is fail");exit(-1);}_size = 0;_capacity = _capacity;}​void Push(const int &data){_array[_size] = data;_size++;}​//拷贝构造Stack(const Stack &st){_array = (int *)malloc(sizeof(int) * st._capacity);if (nullptr == _array){perror("malloc is fail");exit(-1);}memcpy(_array, st._array, sizeof(int) * st._size);_size = st._size;_capacity = st._capacity;}​~Stack(){if (_array){delete[] _array;_array = nullptr;_capacity = 0;_size = 0;}}​private:int *_array;int _size;int _capacity;};​class MyQueue{//默认生成构造 ->生成定义在Stack中的默认构造函数//默认生成析构//默认生成的拷贝构造private:Stack _pushST;Stack _popST;int _size = 0;};​int main(){Stack st1;st1.Push(1);st1.Push(2);st1.Push(3);​Stack st2(st1);cout<<"====="<<endl;MyQueue q;​return 0;}

默认生成拷贝构造和赋值重载:

a.内置类型完成 浅/值 拷贝--按byte一个一个拷贝

b.自定义类型,去调用这个成员 拷贝构造/赋值重载

2.赋值重载

运算符重载

C++为了增强代码的可读性引入了运算符重载运算符重载是具有特殊函数名的函数,也具有其 返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。

函数名字为:关键字operator后面接需要重载的运算符符号。 函数原型:返回值类型 operator操作符(参数列表)

自定义类型不能直接使用运算操作符 内置类型是语法定义,而自定义类型为人为定义,编译器并不知道该如何进行比较,这便出现了operator用函数完成

运算符重载:自定义类型对象可以使用运算符

函数重载:支持函数名相同,参数不同的函数

 
#include <iostream>using namespace std;​class Date{public:// 构造函数Date(int year = 1, 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;}​void Print(){cout << _year << "/" << _month << "/" << _day << endl;}​// d1==d2 -> d1.operator==(d2)bool operator==(const Date &d){return _year == d._year && _month == d._month && _day == d._day;//    this->_year==d.year}​private:// 成员变量int _year;int _month;int _day;};​int main(){Date d1(2077, 2, 4);Date d2(2077, 2, 4);​// d1==d2;cout << d1.operator==(d2) << endl;cout << (d1 == d2) << endl;​return 0;}

注意:

  • 不能通过连接其他符号来创建新的操作符:比如operator

  • 重载操作符必须有一个类类型参数

  • 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不能改变其含义

  • 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐 藏的this现。

  • 注意以下5个运算符不能重载

     .*   ::  sizeof  ?:   .

== <= < >= > !=
// d1==d2 -> d1.operator==(d2)bool operator==(const Date &d){return _year == d._year && _month == d._month && _day == d._day;//    this->_year==d.year}​// 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;//     }//     else//         return false;// }​// d1<d2bool operator<(const Date &d){return _year < d._year && (_year == d._year && _month < d._month) && (_year == d._year && _month == d._month && _day < d._day);}

任何一个类都适用于,当写了一个>=或<=那其他的就可以进行复用

     // d1<=d2bool operator<=(const Date &d){return *this < d || *this == d;//*this就是d1}

这个地方对operator<(const Date &d)进行了复用。operator<=(const Date &d)中的表达式*this < d调用了operator<(const Date &d)来判断两个日期对象的大小关系。同时,operator<=(const Date &d)还利用operator==(const Date &d)来判断两个日期对象是否相等。通过这样的复用方式,可以简化代码并提高代码的可读性

     // d1>d2bool operator>(const Date &d){return !(*this<= d);}​//d1>=d2bool operator>=(const Date& d){return !(*this<d);}​//d1!=d2bool operator!=(const Date& d){return !(*this ==d);}

当然赋值运算符不使用&并不会无限循环

    // d1<=d2bool operator<=(const Date d){return *this < d || *this == d;}

当然可以不用,但是最好还是加上

连续赋值

d3 = d1 = d2

     // 因为Date operator=(const Date &d) 出了该函数的作用域*this/d1 还在此时返回的*this是临时拷贝,需要进行拷贝重新开空间造成浪费,不如直接进行&Date operator=(const Date &d)//&d 引用{if (this != &d)//防止d1=d1进行赋值 此处的&为去地址 ,若this与d的地址一样则无需赋值{_year = d._year;_month = d._month;_day = d._day;}​return *this; //*this就是d1}                 // 返回值为了支持连续赋值,保持运算符特性  d3=d1=d2;

当然要注意,赋值重载是针对已经创造的对象

 Date d5=d1;//拷贝构造

像这样就是拷贝构造

同样作为默认成员函数,可以不用手动写

源码:

 #include <iostream>using namespace std;​class Date{public:// 构造函数Date(int year = 1, 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;}​void Print(){cout << _year << "/" << _month << "/" << _day << endl;}// d1==d2 -> d1.operator==(d2)bool operator==(const Date &d){return _year == d._year && _month == d._month && _day == d._day;//    this->_year==d.year}​// d1<d2bool operator<(const Date &d){return _year < d._year && (_year == d._year && _month < d._month) && (_year == d._year && _month == d._month && _day < d._day);}​// d1<=d2bool operator<=(const Date &d){return *this < d || *this == d; //*this就是d1}​// d1>d2bool operator>(const Date &d){return !(*this <= d);}​// d1>=d2bool operator>=(const Date &d){return !(*this < d);}​// d1!=d2bool operator!=(const Date &d){return !(*this == d);}​// // 因为Date operator=(const Date &d) 出了该函数的作用域*this/d1 还在此时返回的*this是临时拷贝,需要进行拷贝重新开空间造成浪费,不如直接进行&// Date operator=(const Date &d)//&d 引用// {//     if (this != &d)//防止d1=d1进行赋值 此处的&为去地址 ,若this与d的地址一样则无需赋值//     {//         _year = d._year;//         _month = d._month;//         _day = d._day;//     }​//     return *this; //*this就是d1// }                 // 返回值为了支持连续赋值,保持运算符特性  d3=d1=d2;​private:// 成员变量int _year;int _month;int _day;};​int main(){Date d1(2077, 2, 4);Date d2(2222, 3, 2);Date d3(2078, 2, 4);​cout << (d1 < d2) << endl;// d3 = d1 = d2;​d1 = d2;d1.Print();​return 0;}

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

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

相关文章

Python学习笔记--类和对象

五、类和对象 1、类和对象之间的关系 这部分内容主要讲类和对象,我们先来说说类和对象之间的关系。 类是对象的模板 我们得先有了类,才能制作出对象。 类就相对于工厂里面的模具,对象就是根据模具制造出来的产品。 从模具变成产品的过程,我们就称为类的实例化。 类实…

POJ 3981:字符串替换 ← C++

【题目来源】http://poj.org/problem?id3981【题目描述】 编写一个C程序实现将字符串中的所有"you"替换成"we"。【输入格式】 输入包含多行数据。 每行数据是一个字符串&#xff0c;长度不超过1000。 数据以EOF结束。【输出格式】 对于输入的每一行&#…

【开源】基于SpringBoot的海南旅游景点推荐系统的设计和实现

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用户端2.2 管理员端 三、系统展示四、核心代码4.1 随机景点推荐4.2 景点评价4.3 协同推荐算法4.4 网站登录4.5 查询景点美食 五、免责说明 一、摘要 1.1 项目介绍 基于VueSpringBootMySQL的海南旅游推荐系统&#xff…

P1022 [NOIP2000 普及组] 计算器的改良 题解

文章目录 题目背景题目描述输入格式输出格式样例样例输入样例输出 思路及部分实现完整代码 题目背景 NCL 是一家专门从事计算器改良与升级的实验室&#xff0c;最近该实验室收到了某公司所委托的一个任务&#xff1a;需要在该公司某型号的计算器上加上解一元一次方程的功能。实…

2017年上半年上午易错题(软件设计师考试)

CPU 执行算术运算或者逻辑运算时&#xff0c;常将源操作数和结果暂存在&#xff08; &#xff09;中。 A &#xff0e; 程序计数器 (PC) B. 累加器 (AC) C. 指令寄存器 (IR) D. 地址寄存器 (AR) 某系统由下图所示的冗余部件构成。若每个部件的千小时可靠度都为 R &…

【Python机器学习】零基础掌握partial_dependence检验、检查

在医疗健康的领域,有一个问题一直困扰着专家——如何从多个健康指标中找出影响患者健康最关键的因素?在这样的场景下,做出准确的预测非常关键,因为它直接关联到患者的生命安全。 解决这一问题的一个有效方法是利用机器学习算法,具体来说就是通过偏依赖图(Partial Depend…

微信小程序在线预览PDF文件

需求&#xff1a;微信小程序在线预览PDF合同文件&#xff0c;加载完成后强制阅读10秒才可点击同意按钮 H5代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" cont…

如何使用手机蓝牙设备作为电脑的解锁工具像动态锁那样,蓝牙接近了电脑,电脑自动解锁无需输入开机密码

环境&#xff1a; Win10 专业版 远程解锁 蓝牙解锁小程序 问题描述&#xff1a; 如何使用手机蓝牙设备作为电脑的解锁工具像动态锁那样&#xff0c;蓝牙接近了电脑&#xff0c;电脑自动解锁无需输入开机密码 手机不需要拿出来&#xff0c;在口袋里就可以自动解锁&#xff…

nlp之加载电商评论集

目录 代码代码解读 代码 import pandas as pddf pd.read_csv("../data/Clothing Reviews.csv") print(df.info())df[Review Text] df[Review Text].astype(str) x_train df[Review Text] y_train df[Rating]from tensorflow.keras.preprocessing.text import To…

Geeker-Admin中ProTable表格分页之自定义接口页码、尺寸参数

最近挖了个新玩意儿&#xff0c;Geeker-Admin&#xff0c;看起来感觉挺好。 鼓捣了半天搞定了与服务端的API接口对接&#xff0c;但在表格分页的时候又遇到了问题&#xff0c;系统默认是pageNum/pageSize这两个参数名用来分页&#xff0c;而服务端是current/size&#xff0c;开…

C#,数值计算——分类与推理,基座向量机的 Svmgenkernel的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { public abstract class Svmgenkernel { public int m { get; set; } public int kcalls { get; set; } public double[,] ker { get; set; } public double[] y { get; set…

微信小程序瀑布流组件

话不多说直接上干货: 现在component中创建一个waterfull的文件夹&#xff0c;并创建对应的wxml,wxss,jx,json文件 wxml&#xff1a; <view class"content"><view class"content-left"><block wx:for"{{list}}" wx:key"…

机器学习-特征选择:如何使用互信息特征选择挑选出最佳特征?

一、引言 特征选择在机器学习中扮演着至关重要的角色&#xff0c;它可以帮助我们从大量的特征中挑选出对目标变量具有最大预测能力的特征。互信息特征选择是一种常用的特征选择方法&#xff0c;它通过计算特征与目标变量之间的互信息来评估特征的重要性。 互信息是信息论中的一…

前端线上部署,如何通知用户有新版本

前言 version-polling 是一个轻量级的 JavaScript 库&#xff0c;它可以实时检测 web 应用的 index.html 文件内容是否有变化。当服务端发布新版本后&#xff0c;前端会自动弹出更新提示&#xff0c;让用户刷新页面&#xff0c;以加载最新的资源和功能。这样可以提高用户体验和…

verilog vscode linux

安装 vscode 插件 插件&#xff1a;Verilog-HDL/SystemVerilog/Bluespec SystemVerilog 功能&#xff1a;.xdc .ucf .v 等代码高亮、代码格式化、语法检查&#xff08;Linting&#xff09;、光标放到变量上提示变量的信息等 关于其他语言的依赖工具等信息查看插件说明 代码对齐…

Csdn文章编写参考案例

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

解决visual studio Just-In-Time Debugger调试

解决visual studio Just-In-Time Debugger调试 网上流行很多方法&#xff0c;最后一直不行&#xff0c;其实有最简单的方法比较实用 方法一&#xff1a;把 C:\WINDOWS\system32\vsjitdebugger.exe,删除了&#xff0c;若怕出问题&#xff0c;可以把它改名或者做个rar文件暂时保留…

cosover是什么?crossover23又是什么软件

cosover是篮球里的过人技巧。 1.crossover在篮球中的本意是交叉步和急速交叉步。crossover 是篮球术语&#xff0c;有胯下运球、双手交替运球&#xff0c;交叉步过人、急速大幅度变向等之意。 2.在NBA里是指包括胯下运球、变向、插花在内的过人的技巧。 NBA有很多著名的Cross…

获取客户端请求IP及IP所属城市

添加pom依赖 <dependency> <groupId>org.lionsoul</groupId> <artifactId>ip2region</artifactId> <version>2.6.5</version> </dependency> public class IpUtil { private…

Linux进程等待

一、进程等待是什么&#xff1f; 通过系统调用wait/waitpid&#xff0c;来对子进程进行状态检验与回收的工作。 二、为什么要有进程等待 1、子进程退出&#xff0c;父进程如果不管不顾&#xff0c;就可能造成‘僵尸进程’的问题&#xff0c;进而造成内存泄漏。 另外&#xf…