C++类和对象(中)
✨个人主页: Yohifo
🎉所属专栏: C++修行之路
🎊每篇一句: 图片来源
I do not believe in taking the right decision. I take a decision and make it right.
- 我不相信什么正确的决定。我都是先做决定,然后把事情做好。
文章目录
- 📘前言
- 📘正文
- 📖默认成员函数
- 📖构造函数
- 🖋️默认构造函数
- 🖋️新增补丁
- 📖析构函数
- 🖋️默认析构函数
- 📖拷贝构造函数
- 🖋️默认拷贝构造函数
- 🖋️无穷递归
- 🖋️浅拷贝
- 🖋️深拷贝
- 🖋️小结
- 📖运算符重载
- 🖋️operator操作符
- 🖋️使用注意
- 📖赋值重载函数
- 🖋️默认赋值重载函数
- 🖋️深度赋值
- 🖋️注意事项
- 📖const修饰
- 🖋️修饰*this
- 📖取地址重载函数
- 📖const修饰的取地址重载函数
- 📘总结
📘前言
祖师爷在设计 C++
中的类时,规定每个类中都有六个默认成员函数
,即使我们不主动写,编译器也会自动生成,这些成员函数就是神秘的天选之子,不仅神秘,而且还很强大,可以这么说:类和对象的是否学懂,取决于对这几个天选之子的理解程度。本文将会逐一介绍这几个默认成员函数,跟随我的脚步,一起揭开他们的神秘面纱
注意:以上函数都需要加上 “默认” 前缀,因为编译器自动生成并调用的是
默认成员函数
📘正文
📖默认成员函数
祖师爷规定,每个类中都必须有这六个默认成员函数:
- 默认构造函数 重要
- 默认析构函数 重要
- 默认拷贝构造函数 较重要
- 默认赋值重载函数 较重要
- 默认取地址重载函数 一般
- 默认
const
取地址重载函数 一般
虽说都是祖师爷钦定的天选之子,但最后两个相对来说比较简单,因此介绍也会比较少
默认成员函数规则比较多,尤其是构造
和析构
,当初祖师爷在设计的时候,部分地方设计欠佳,导致后人在学习 C++
时,额外增加了不少学习成本
下面就来看看祖师爷是如何设计的、出了什么问题、以及是怎么解决的
📖构造函数
构造函数是祖师爷首先钦定的天选之子
构造函数诞生的目的是为了减少频繁手动初始化的问题,将初始化这个事情变成自动化处理
将C语言
和C++
都看作车辆,初始化操作看作换挡,可以这样认为:
C语言
依赖于手动操作,就像手动挡车辆,有驾驶乐趣,但比较麻烦C++
面向对象自动操作,就像自动挡车辆,上手简单,驾驶难度低
我们是可以自己编写构造函数的,祖师爷给了我们这个权力,他钦定的天选之子是默认构造函数,由编译器自动生成,并供类默认调用的,下面来看看编写构造函数的规则
本文介绍的函数都属于特殊函数,规则和普通函数不同
构造函数创建规则:
- 函数名和类名相同
- 不需要返回值,甚至连
void
都不需要写 - 对象实例化时,编译器
自动调用默认构造函数
- 构造函数支持重载,即可以存在多个构造函数,
但默认构造函数只能有一个
构造函数还有一种特殊形式:默认构造函数
语法规定,不带参数或参数为全缺省的构造函数称为默认构造函数
默认构造函数有两种写法,推荐全缺省参数的形式
class Date
{
public://特别注意:默认构造函数只允许存在一个形式//一般推荐使用形式二:全缺省参数//因为这样方便后续初始化时指定值默认构造函数形式一:不带参数//Date()//{// _year = 1970;// _month = 1;// _day = 1;//}//默认构造函数形式二:参数为全缺省Date(int year = 1970, int month = 1, int day = 1){_year = year;_month = month;_day = day;cout << "Date(int year = 1970, int month = 1, int day = 1)" << endl;}//其他普通构造函数,只要与默认构造函数构成重载,都合法Date(double b){_year = 2023;_month = 2;_day = 9;cout << "Date(double b)" << endl;}//……private:int _year;int _month;int _day;
};
严格来说,现阶段的初始化方式不规范,此时为赋值
正确的初始化方式是使用初始化列表,当然这个东西在下篇介绍
出自 《Effective C++》
当构造函数写好后,我们就可以这样使用:
int main()
{//调用默认构造函数,d1 初始化为1970 1 1Date d1; //相当于 Date d1(); 但不能这样写//因为调用的是全缺省参数的默认构造函数,我们也可以传参数//Date d1(2001, 1, 1); //这种初始化也是合法的//调用自定义构造函数Date d2(1.1);return 0;
}
构造函数允许重载,因此调用不会冲突,运行结果如下:
🖋️默认构造函数
如果我们没写默认构造函数, 就会由编译器自动生成,这是祖师爷制定的规则;假如我们写了,同时也满足默认构造函数的需求,编译器就会以我们写的为准,并转而调用我们写的默认构造函数
注:默认构造函数就是调用时,不需要传参的构造函数
默认构造函数形式一:不带参数//Date()//{// _year = 1970;// _month = 1;// _day = 1;//}//默认构造函数形式二:参数为全缺省Date(int year = 1970, int month = 1, int day = 1){_year = year;_month = month;_day = day;cout << "Date(int year = 1970, int month = 1, int day = 1)" << endl;}
这里暂时无法给大家演示编译器自动生成并调用的现象
因为祖师爷在设计默认构造函数时,埋下了一个坑:
- 默认构造函数不对内置数据类型做处理,如
int
、double
、char
等 - 至于自定义类型,默认构造函数会去调用属于它们的初始化函数(默认构造函数)
注意:数据类型主要分为两类 <内置类型和自定义类型>
简言之:默认构造函数有点像不干实事的函数
假设我们的类中只有内置类型,那么默认构造函数真就什么都没有做;出现自定义类型时,也只会主动去调用它的默认构造函数,至于自定义类型的默认构造函数干了什么,类的默认构造函数是不管的
因祖师爷设计疏忽而留下的坑,为后世学习C++
增加了阻力
这么看来,这个天选之子似乎没有什么用,默认构造函数还得我们自己编写
不过在有些场景下,默认构造函数很有用
- 题目:用栈实现队列
- 需要在队列这个类中,调用两个栈类,实现队列类
- 此时我们只需要写好栈的
默认构造函数
- 队列类的
默认构造函数
不需要写,因为自动生成的会去调用自定义类型的默认构造函数
,即栈的默认构造函数
,显然是存在的
为了解决祖师爷留下来的坑,委员会在C++11
标准中新增了一个补丁声明时给缺省值
🖋️新增补丁
这个补丁是新标准中的,可能部分老编译器不支持
具体操作很简单:在成员变量声明时,将内置类型给上缺省值,调用编译器生成的默认构造函数时,就会以这些缺省值来初始化成员变量,达到初始化的效果
注意:此时给的是缺省值,并非在声明阶段赋值,类中成员变量为声明阶段
class Date
{
private:int _year = 2023; //在内置类型声明时给上缺省值int _month = 2; //这样即使调用生成的默认构造函数int _day = 9; //也能达到初始化的效果
};
有了补丁辅助我们后,就可以看看编译器是否调用了默认构造函数
在打了补丁的情况下,实例化一个对象,可以看到效果如下:
C++11
中的补丁可以解决内置类型不初始化这个问题,但相对来说,全缺省参数形式的默认构造函数
更加实用,不仅能初始化,还能指定初始化值
注意:这个补丁是为内置类型准备的,对于自定义类型,默认构造函数会去调用属于它的默认构造函数
在涉及开辟空间的初始化行为时,可以先给 nullptr,再到默认构造函数体内开辟空间
📖析构函数
析构函数就是另一个天选之子了
构造函数: 解决频繁初始化操作
析构函数: 解决频繁销毁操作
不难看出,这是两兄弟,一个负责做菜,一个负责洗碗
此时仍然是手动挡和自动挡的区别
析构函数和构造函数师出同门,规则也都差不多
析构函数创建规则:
- 函数名在类名的前面加上
~
- 也没有返回值,连
void
都不需要写 - 对象声明周期结束时,编译器会
自动调用默认析构函数
- 析构函数不支持重载,毕竟不能对同一个对象销毁多次
析构函数也有一种特殊形式:默认析构函数
不过因为析构函数不支持重载,所以默认与否已经不重要了,如果我们写了,编译器就用我们写的默认析构函数,否则就用编译器自动生成的
默认析构函数也存在默认构造函数的坑:对内置类型不作处理
🖋️默认析构函数
如果我们没写,编译器会自动生成默认析构函数,假如我们写了,编译器就会用我们写的
注:默认析构函数是在对象生命周期结束时自动调用
class Date
{
public://析构函数写法比较特殊,需要多加注意~Date(){//假设动态开辟了空间//是需要在析构函数中释放的_year = _month = _day = 0;}
private:int _year = 2023;int _month = 2;int _day = 9;
};
同默认构造函数一样,默认析构函数对内置类型也不处理,对自定义类型,会去调用属于它的默认构造函数
默认构造函数不难写,普通自定义类型是否释放问题不大,但涉及动态内存开辟
时,如果不释放内存,就会发生内存泄漏问题,因此当我们的对象涉及动态内存开辟
时,需要自己编写默认析构函数,确保安全问题。
~Test()
{//假设 pa 为动态开辟的空间//需要释放free(pa);pa = nullptr;
}
📖拷贝构造函数
拷贝构造函数 算是 构造函数 的远房亲戚,因为它们的函数名一样,不过参数不同,构成重载
对于内置类型,我们可以通过 = 完成拷贝,对于自定义类型,规则较多,拷贝需要我们自己完成,因此拷贝构造函数应运而生
为何自定义类型不能直接赋值?
因为自定义类型种类繁多,比如栈、队列、树、图,数据结构很复杂,尤其是涉及空间开辟问题时,不能简单通过指针赋值完成拷贝,这样会导致重复析构问题;正确做法是 开辟空间->拷贝数据->更新指向->完成拷贝
int a = 10;
int b = a; //内置类型,简单拷贝(赋值)
拷贝构造函数实现也很简单:
class Date
{
public://拷贝构造函数,此时是简单拷贝,只能用于非动态内存开辟的空间//拷贝构造函数函数名与构造函数相同,不过参数类型为类Date(const Date& d){//d 拷贝给 *this_year = d._year;_month = d._month;_day = d._day;}
private:int _year = 2023;int _month = 2;int _day = 9;
};
使用时有以下两种用法:
Date d1; //将 d1 拷贝给 d2 和 d3
Date d2(d1); //法一Date d3 = d1; //法二
既然是天选之子之一,编译器也会生成默认拷贝构造函数
🖋️默认拷贝构造函数
默认拷贝构造函数 是个懂事的函数,对于内置类型,它不再持有偏见,也就是说默认拷贝构造函数能完成简单内置类型的拷贝操作
正常情况下,即成员变量不涉及空间开辟时,拷贝构造函数 没有必要写,用编译器自动生成的足够了
对于涉及空间开辟的,一定要写默认拷贝构造函数
class SeqList
{
public://现在编写一个涉及空间开辟的拷贝构造函数SeqList(const SeqList& tmp){_pa = (int*)malloc(sizeof(int) * _capacity);if (nullptr == _pa){cout << "malloc fail" << endl;exit(-1); //失败,直接退出程序}//将 tmp 空间中的值,拷贝到 *this 中memcpy(_pa, tmp._pa, sizeof(int) * _size);_size = tmp._size;_capacity = tmp._capacity;}private:int* _pa = nullptr;int _size = 0;int _capacity = 4; //动态顺序表
};
默认拷贝构造函数实现比较简单,但有一个值得注意的大问题:无穷递归
🖋️无穷递归
所谓无穷递归问题就是指设计拷贝构造函数时,参数没有设为引用
如下所示:
SeqList(SeqList tmp)
{//此时必然会引发无穷递归问题//……
}
问题出现原因:值传递,需要先生成临时变量,再传递,而生成临时变量这个行为本身就是在调用拷贝构造函数
也就是说:此时我们在实现拷贝构造函数,但参数又需要拷贝构造函数 这让编译器很难堪
大力士无法举起自己,光靠金针菇也无法完成卡Bug行为
解决方法:因为待拷贝对象本来就已经存在,此时可以使用引用,避免产生临时变量,再加以 const 修饰,保护待拷贝对象
因此正确的拷贝构造函数应该这样写:
SeqList(const SeqList& tmp)
{//有效避免无穷递归问题//……
}
🖋️浅拷贝
浅拷贝 就是简单的逐字节序拷贝
浅拷贝可能出现空间共用的情况
浅拷贝可能引发对同一块空间的重复析构问题
浅拷贝不可取,尤其是在面对复杂数据结构时
🖋️深拷贝
深拷贝需要我们自己实现
深拷贝 在面对空间问题时,会先给 对象2
开辟一块同样大的空间,再将 对象1
空间中的数据拷贝过来
深拷贝中,两个对象的空间是独立的、互不干扰的
深拷贝才是众望所归
当成员涉及复杂数据结构、空间开辟时,就需要写出默认拷贝构造函数
🖋️小结
构造函数家族至此就介绍完成了,简单小结一下:
类型 | 用途 | 处理情况 |
---|---|---|
默认析构函数 | 初始化对象 | 不对内置类型作处理 |
默认析构函数 | 销毁对象 | 也不对内置类型作处理 |
默认拷贝构造函数 | 拷贝对象 | 只能对简单内置类型做处理 |
何时需要自己写默认析构函数?
- 当我们写出
默认拷贝函数
完成复杂对象的拷贝时,就证明需要默认析构函数
来释放对象
小技巧:
- 在函数传参与返回时,如果对象生命周期足够长,就可以考虑使用引用的方式,避免参数走
拷贝构造
->生成临时变量
->再传递
的路线,提高程序运行效率
特别注意: 默认拷贝构造函数与默认构造函数名相同,当我们只写拷贝
而不写构造
时,编译器就会报错,因为此时的拷贝
会被误以为是默认构造函数
也就是说,默认拷贝构造函数存在的前提是默认构造函数已存在
📖运算符重载
C++
支持运算符重载,运算符重载使得自定义类型间的符号运算变成可能
比如:
int a = 1;
int b = 2;
a - b; //合法Date d1;
Date d2;
d1 - d2; //非法,此时需要通过运算符重载解决这个问题//解决方法如下
const Date operator-(const Date& d)
{//简单演示,逻辑存在问题,可以忽略Date tmp(*this); //调用拷贝构造tmp._year -= d._year; //内置类型,可以正常相减tmp._month -= d._month; //同理tmp._day -= d._day; //同上return tmp; //tmp 为临时变量,不能传引用返回
}
此时就可以正常使用 d1 - d2
了
注:运算符重载和函数重载没有关系
🖋️operator操作符
operator
译为运算符,是C++
中新的关键字,operator
的作用很简单,实现自定义类型的运算
使用规则:
operator
函数中的操作数取决于参数个数operator
一般写在类中,方便通过this
指针访问成员变量- 写在类中时,
this
指针就算一个隐藏参数 operator
也可以写在类外,此时会发生无法访问成员变量问题,可以这样解决:- 将成员变量设为
public
(不安全) - 通过函数获取类中的成员变量值 (麻烦)
- 设置为友元函数(也比较麻烦)
- 写在类中,最简单、省事,而且还可以使用
this
指针
- 将成员变量设为
运算符重载是这样用的:
int main()
{//注:此时只是演示,日期类的减法不能这样写Date d1(2023, 2, 9);Date d2(2022, 2, 9);Date d3 = (d1 - d2); //结果为 1 0 0//此时的调用相当于 d1.operator-(d2) //d1 作为 this 对象传递//也可以这样使用Date d4 = operator-(d1, d2);return 0;
}
基于运算符重载,我们可以干很多事情,比如直接通过 []
访问类中的成员,实现两个对象的快速运算等操作
🖋️使用注意
operator
虽然很好,但也有很多使用规则:
operator
操作符就是函数名- 不能与非操作符链接
- 参数中必须有一个自定义类型
- 对于内置运算符,不能改变其含义
- 成员函数的第一个参数为
this
- 有五个运算符不支持重载:
.*
稀有运算符,很少见::
域作用限定符sizeof
操作符? :
三目运算符.
访问成员符
为何运算符能实现重载?
- 跟函数重载同理,保证函数修饰名不同,构成重载
下面是我测试出的部分运算符重载修饰规则:
基于运算符重载,我们可以介绍第四个天选之子:赋值重载函数
📖赋值重载函数
赋值重载函数的实现原理就是运算符重载
此时重载的运算符是 =
赋值重载的目的:将 d1 对象赋值给 d2,非拷贝构造,d1、d2均已存在
class Date
{
public://赋值重载函数Date& operator=(const Date& d){//能用引用的地方,就用引用//避免去走拷贝构造函数//如果传入的是两个相同值,没必要再执行赋值if (this == &d){return *this;}_year = d._year;_month = d._month;_day = d._day;//返回赋值完成的值,即 *thisreturn *this;}
private:int _year = 2023;int _month = 2;int _day = 9;
};
为何传引用?
- 两个对象都已存在,使用引用,提高效率
为何判断相同?
- 避免资源浪费,当类的成员变量很多时,假如出现
d1 = d1 = d1
这种情况时,可以有效避免资源浪费
为何返回 *this
?
- 因为可能出现重复赋值的情况,如
d1 = d2 = d3
赋值重载函数不难实现,只是需要注意的地方很多
🖋️默认赋值重载函数
祖师爷在实现默认赋值重载函数时,实现的几乎已经很好了,无论是内置类型还是自定义类型,都会处理
不过默认赋值重载函数仍然是基于字节序的浅赋值,在面对空间开辟时,仍然需要我们自己编写深度赋值重载函数,否则就会发生重复析构问题
🖋️深度赋值
深度赋值的实现和深拷贝几乎一模一样,这里就不加以赘述
一但对象中涉及动态内存开辟,必须自己实现深度拷贝
🖋️注意事项
拷贝构造
和 赋值重载
存在本质区别,一个是对象尚未实例化,另一个是两个对象都已存在
当两个对象都被创建,并发生赋值行为时,才叫做赋值重载
Date d1;
Date d2(d1); //拷贝构造,d2 未存在
Date d3 = (d1 - d2); //赋值重载,d1、d2 已存在
涉及空间资源管理时,必须实现深度拷贝
设计赋值重载函数
时,充分利用引用,提高效率
📖const修饰
const
修饰可以提高程序的健壮性
const
常被用来修饰引用、指针
当被指向对象为常量或临时变量时,必须使用 const
修饰,避免出现权限放大问题
//int* pa = 10; //错误,10 具有常性
const int* pa = (const int*)10; //成功,此时 pa 为常量指针//int& pb = 20; //错误,20 具有常性
const int& pb = 20; //成功引用,此时 pb = 20
const
一般用来修饰指针参数或引用参数,确保参数在使用过程中不被修改
🖋️修饰*this
引入:两个日期 d1、d2,d1 - d2 时,d1 需要被修改,但 d2 不能被修改,因此实现 operator- 时,参数 d 为 const Date& 类型
我们在实现函数时,存在这种情况 确保 *this 不被修改,即 this 指针指向内容不被修改
this
指针太危险了,如果不加以保护的话,可能实现者的不经意行为会导致严重的后果
class Date
{
public://实现简单的打印函数void Print(){ cout << _year << "年";cout << _month << "月";cout << _day << "日";cout << endl//有可能不小心出现这样的情况_year = _month = _day;//此时该对象就危险了,成员变量全被改了}private:int _year = 2023;int _month = 2;int _day = 9;
};
this
指针给了我们足够的自由,我们在使用时也应该尊重它
class Date
{
public://实现简单的打印函数//原指针类型为 Date* const ,只允许指向对象//修改指针类型为 const Date* const 双重保护void Print() const{ cout << _year << "年";cout << _month << "月";cout << _day << "日";cout << endl//有可能不小心出现这样的情况_year = _month = _day; //此时会报错,因为 this 指针类型为 const Date* const//此时该对象就危险了,成员变量全被改了}private:int _year = 2023;int _month = 2;int _day = 9;
};
除了上述情况外,还可能存在这种情况:
const Date d1;
//此时 d1 具有常性,普通的 this 指针无法调动,需要使用 const 指针
总之,const
可以修饰this
指针,起到保护和权限平移交接的效果
📖取地址重载函数
接下来简单介绍一下剩下两个天选之子
取地址重载函数
- 获取当前对象的地址
class Date
{
public:Date* operator&(){return this;}
private:int _year = 2023;int _month = 2;int _day = 9;
};
📖const修饰的取地址重载函数
const修饰的取地址重载函数
- 获取
const
修饰对象的地址
class Date
{
public:const Date* operator&() const{return this;}
private:int _year = 2023;int _month = 2;int _day = 9;
};
这两个默认成员函数
都很简单,使用编译器默认生成的就够了,除非我们不想让别人获取到当前地址,直接手动设置,每次都返回 nullptr
,当然这种情况几乎不存在
开发者何必为难开发者
📘总结
以上就是关于 类和对象(中)
的全部内容了,本文主要侧重点为 六大天选之子
,以及编译器自动生成的默认成员函数
,何时用编译器的、何时用我们自己写的,都是有讲究的,部分成员函数规则多、实现麻烦,需要多加练习以加深理解。这里推荐日期类
的实现练习,能让我们对类和对象
有一个更深层次的理解,关于日期类
的实现,我将会在下篇文章中介绍,敬请期待!
如果你觉得本文写的还不错的话,期待留下一个小小的赞👍,你的支持是我分享的最大动力!
如果本文有不足或错误的地方,随时欢迎指出,我会在第一时间改正
…
相关文章推荐
类和对象(上)
C++入门基础
![]()
相关文章:

C++类和对象(中)
✨个人主页: Yohifo 🎉所属专栏: C修行之路 🎊每篇一句: 图片来源 I do not believe in taking the right decision. I take a decision and make it right. 我不相信什么正确的决定。我都是先做决定,然后把…...

Docker安装EalasticSearch、Kibana,安装Elasticvue插件
使用Docker快速安装部署ES和Kibana的前提:首先需要确保已经安装了Docker环境。 如果没有安装Docker的话,先在Linux上安装Docker。 有了Docker环境后,就可以使用Docker安装部署ES和Kibana了 一、安装ES 1、拉取EalasticSearch镜像 docker p…...

算法训练营 day39 贪心算法 无重叠区间 划分字母区间 合并区间
算法训练营 day39 贪心算法 无重叠区间 划分字母区间 合并区间 无重叠区间 435. 无重叠区间 - 力扣(LeetCode) 给定一个区间的集合 intervals ,其中 intervals[i] [starti, endi] 。返回 需要移除区间的最小数量,使剩余区间互…...

c/c++开发,无可避免的文件访问开发案例
一、缓存文件系统 ANSI C标准中的C语言库提供了fopen, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, freopen, fseek, ftell, rewind等标准函数,这些函数在不同的操作系统中应该调用不同的内核API,从而支持开发者跨平台实现对文件的访问。 在Lin…...
MySQL学习笔记
MySQL学习笔记一、基础配置二、数据库操作三、表的操作1.创建表2.表选项3.查看表4.修改表5.删除表6.复制表7.检查优化修复表四、数据操作基础增删改查五、字符集编码六、数据类型(列类型)1.数值类型2.字符串类型3.日期时间类型4.枚举和集合七、列属性&am…...

ccs导入工程失败的处理方法
文章目录当导入CCS新工程时出现下述错误怎么办?方法一 从TI官网下载安装包进行安装,下载链接:软件下载完成 安装路径为上面的文件夹点击安装完成后,导入安装路径,并点击Refresh按钮,依据路径进行更新&#…...

探针台常见的故障及解决方法
症状、 可能原因、 解决方法 移动样品后画面变模糊 —显微镜不垂直,调垂直显微镜 样品台不水平 —调水平样品台 显微镜视场亮度不足,边缘切割或看不到像—转换器不在定位位置上 把转换器转到定位位置上 管镜转盘不在定位位置上 —把管镜转盘转到定…...
域内资源探测
✅作者简介:CSDN内容合伙人、信息安全专业在校大学生🏆 🔥系列专栏 :内网安全 📃新人博主 :欢迎点赞收藏关注,会回访! 💬舞台再大,你不上台,永远是…...

c# 将数据导出到EXCEL文件
第一步:项目中加入引用。 在鼠标右击项目,点击【添加】弹出菜单列表,选择【项目引用】弹出【引用管理器】对话框,选择【COM】-【Microsoft Excel 16.0 Object Library】,如图所示: 第二步,编辑…...

微服务 分片 运维管理
微服务 分片 运维管理分片分片的概念分片案例环境搭建案例改造成任务分片Dataflow类型调度代码示例运维管理事件追踪运维平台搭建步骤使用步骤分片 分片的概念 当只有一台机器的情况下,给定时任务分片四个,在机器A启动四个线程,分别处理四个…...
批量占满TEMP表空间问题处理与排查
批量占满TEMP表空间问题处理与排查应急处置问题排查查看占用TEMP表空间高的SQL获取目标SQL执行计划方法一:EXPLAIN PLAN FOR方法二:DBMS_XPLAN.DISPLAY_CURSOR方法三:DBMS_XPLAN.DISPLAY_AWR方法四:AUTOTRACE数据库跑批任务占满TE…...
Pytorch中的tensor和variable
Tensor与Variable pytorch两个基本对象:Tensor(张量)和Variable(变量) 其中,tensor不能反向传播,variable可以反向传播(forword)。 反向传播是为了让神经网络更新前面…...

暗月内网渗透实战——项目七
首先环境配置 VMware的网络配置图 环境拓扑图 开始渗透 信息收集 使用kali扫描一下靶机的IP地址 靶机IP:192.168.0.114 攻击机IP:192.168.0.109 获取到了ip地址之后,我们扫描一下靶机开放的端口 靶机开放了21,80,999,3389,5985,6588端口…...

【Java 面试合集】描述下Objec类中常用的方法(未完待续中...)
描述下Objec类中常用的方法 1. 概述 首先我们要知道Object 类是所有的对象的基类,也就是所有的方法都是可以被重写的。 那么到底哪些方法是我们常用的方法呢??? cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringw…...

SQLSERVER 的 truncate 和 delete 有区别吗?
一:背景 1. 讲故事 在面试中我相信有很多朋友会被问到 truncate 和 delete 有什么区别 ,这是一个很有意思的话题,本篇我就试着来回答一下,如果下次大家遇到这类问题,我的答案应该可以帮你成功度过吧。 二࿱…...

【C++】CC++内存管理
就是你被爱情困住了?Wake up bro! 文章目录一、C/C内存分布二、C语言中动态内存管理方式三、C中内存管理方式1.new和delete操作内置类型2.new和delete操作自定义类型(仅限vs的底层实现机制,new和delete一定要匹配使用,…...
数据预处理之图像去空白
数据预处理之图像去空白图像去空白介绍方法边缘检测阈值处理形态学图像剪切图像去空白 介绍 图像去空白是指在图像处理中去除图像中的空白区域的过程。空白区域通常是指图像中的白色或其他颜色,其不包含有用的信息。去空白的目的是为了节省存储空间、提高图像处理…...

真的麻了,别再为难软件测试员了......
前言 有不少技术友在测试群里讨论,近期的面试越来越难了,要背的八股文越来越多了,考察得越来越细,越来越底层,明摆着就是想让我们徒手造航母嘛!实在是太为难我们这些测试工程师了。 这不,为了帮大家节约时…...
2月9日,30秒知全网,精选7个热点
///货拉拉将推出同城门到门跑腿服务 据介绍,两轮电动车将成为该业务的主要运力,预计将于3月中旬全面开放骑手注册和用户人气征集活动,并根据人气和线上骑手注册情况选择落地城市,于4月正式开放服务和骑手接单 ///三菱、乐天和莱茵…...

球面坐标系下的三重积分
涉及知识点 三重积分球面坐标系点火公式一些常见积分处理手法 球面坐标系定义 球面坐标系由方位角φ\varphiφ、仰角θ\thetaθ和距离rrr构成 直角坐标系(x,y,z)(x,y,z)(x,y,z)到球面坐标系的(r,φ,θ)(r,\varphi,\theta)(r,φ,θ)的转化规则如下: {xrsinφco…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...