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

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;}

这里暂时无法给大家演示编译器自动生成并调用的现象
因为祖师爷在设计默认构造函数时,埋下了一个

  • 默认构造函数不对内置数据类型做处理,如 intdoublechar
  • 至于自定义类型,默认构造函数会去调用属于它们的初始化函数(默认构造函数)

注意:数据类型主要分为两类 <内置类型和自定义类型>

简言之:默认构造函数有点像不干实事的函数

假设我们的类中只有内置类型,那么默认构造函数真就什么都没有做;出现自定义类型时,也只会主动去调用它的默认构造函数,至于自定义类型的默认构造函数干了什么,类的默认构造函数是不管的

默认构造函数
因祖师爷设计疏忽而留下的坑,为后世学习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
  • 有五个运算符不支持重载:
    1. .* 稀有运算符,很少见
    2. :: 域作用限定符
    3. sizeof 操作符
    4. ? : 三目运算符
    5. . 访问成员符

为何运算符能实现重载?

  • 跟函数重载同理,保证函数修饰名不同,构成重载

下面是我测试出的部分运算符重载修饰规则:
运算符重载
基于运算符重载,我们可以介绍第四个天选之子:赋值重载函数

📖赋值重载函数

赋值重载函数的实现原理就是运算符重载
此时重载的运算符是 =

赋值重载的目的:将 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++类和对象(中)

✨个人主页&#xff1a; Yohifo &#x1f389;所属专栏&#xff1a; C修行之路 &#x1f38a;每篇一句&#xff1a; 图片来源 I do not believe in taking the right decision. I take a decision and make it right. 我不相信什么正确的决定。我都是先做决定&#xff0c;然后把…...

Docker安装EalasticSearch、Kibana,安装Elasticvue插件

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

算法训练营 day39 贪心算法 无重叠区间 划分字母区间 合并区间

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

c/c++开发,无可避免的文件访问开发案例

一、缓存文件系统 ANSI C标准中的C语言库提供了fopen, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, freopen, fseek, ftell, rewind等标准函数&#xff0c;这些函数在不同的操作系统中应该调用不同的内核API&#xff0c;从而支持开发者跨平台实现对文件的访问。 在Lin…...

MySQL学习笔记

MySQL学习笔记一、基础配置二、数据库操作三、表的操作1.创建表2.表选项3.查看表4.修改表5.删除表6.复制表7.检查优化修复表四、数据操作基础增删改查五、字符集编码六、数据类型&#xff08;列类型&#xff09;1.数值类型2.字符串类型3.日期时间类型4.枚举和集合七、列属性&am…...

ccs导入工程失败的处理方法

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

探针台常见的故障及解决方法

症状、 可能原因、 解决方法 移动样品后画面变模糊 —显微镜不垂直&#xff0c;调垂直显微镜 样品台不水平 —调水平样品台 显微镜视场亮度不足&#xff0c;边缘切割或看不到像—转换器不在定位位置上 把转换器转到定位位置上 管镜转盘不在定位位置上 —把管镜转盘转到定…...

域内资源探测

✅作者简介&#xff1a;CSDN内容合伙人、信息安全专业在校大学生&#x1f3c6; &#x1f525;系列专栏 &#xff1a;内网安全 &#x1f4c3;新人博主 &#xff1a;欢迎点赞收藏关注&#xff0c;会回访&#xff01; &#x1f4ac;舞台再大&#xff0c;你不上台&#xff0c;永远是…...

c# 将数据导出到EXCEL文件

第一步&#xff1a;项目中加入引用。 在鼠标右击项目&#xff0c;点击【添加】弹出菜单列表&#xff0c;选择【项目引用】弹出【引用管理器】对话框&#xff0c;选择【COM】-【Microsoft Excel 16.0 Object Library】&#xff0c;如图所示&#xff1a; 第二步&#xff0c;编辑…...

微服务 分片 运维管理

微服务 分片 运维管理分片分片的概念分片案例环境搭建案例改造成任务分片Dataflow类型调度代码示例运维管理事件追踪运维平台搭建步骤使用步骤分片 分片的概念 当只有一台机器的情况下&#xff0c;给定时任务分片四个&#xff0c;在机器A启动四个线程&#xff0c;分别处理四个…...

批量占满TEMP表空间问题处理与排查

批量占满TEMP表空间问题处理与排查应急处置问题排查查看占用TEMP表空间高的SQL获取目标SQL执行计划方法一&#xff1a;EXPLAIN PLAN FOR方法二&#xff1a;DBMS_XPLAN.DISPLAY_CURSOR方法三&#xff1a;DBMS_XPLAN.DISPLAY_AWR方法四&#xff1a;AUTOTRACE数据库跑批任务占满TE…...

Pytorch中的tensor和variable

Tensor与Variable pytorch两个基本对象&#xff1a;Tensor&#xff08;张量&#xff09;和Variable&#xff08;变量&#xff09; 其中&#xff0c;tensor不能反向传播&#xff0c;variable可以反向传播&#xff08;forword&#xff09;。 反向传播是为了让神经网络更新前面…...

暗月内网渗透实战——项目七

首先环境配置 VMware的网络配置图 环境拓扑图 开始渗透 信息收集 使用kali扫描一下靶机的IP地址 靶机IP&#xff1a;192.168.0.114 攻击机IP&#xff1a;192.168.0.109 获取到了ip地址之后&#xff0c;我们扫描一下靶机开放的端口 靶机开放了21,80,999,3389,5985,6588端口…...

【Java 面试合集】描述下Objec类中常用的方法(未完待续中...)

描述下Objec类中常用的方法 1. 概述 首先我们要知道Object 类是所有的对象的基类&#xff0c;也就是所有的方法都是可以被重写的。 那么到底哪些方法是我们常用的方法呢&#xff1f;&#xff1f;&#xff1f; cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringw…...

SQLSERVER 的 truncate 和 delete 有区别吗?

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

【C++】CC++内存管理

就是你被爱情困住了&#xff1f;Wake up bro&#xff01; 文章目录一、C/C内存分布二、C语言中动态内存管理方式三、C中内存管理方式1.new和delete操作内置类型2.new和delete操作自定义类型&#xff08;仅限vs的底层实现机制&#xff0c;new和delete一定要匹配使用&#xff0c;…...

数据预处理之图像去空白

数据预处理之图像去空白图像去空白介绍方法边缘检测阈值处理形态学图像剪切图像去空白 介绍 图像去空白是指在图像处理中去除图像中的空白区域的过程。空白区域通常是指图像中的白色或其他颜色&#xff0c;其不包含有用的信息。去空白的目的是为了节省存储空间、提高图像处理…...

真的麻了,别再为难软件测试员了......

前言 有不少技术友在测试群里讨论&#xff0c;近期的面试越来越难了&#xff0c;要背的八股文越来越多了,考察得越来越细&#xff0c;越来越底层&#xff0c;明摆着就是想让我们徒手造航母嘛&#xff01;实在是太为难我们这些测试工程师了。 这不&#xff0c;为了帮大家节约时…...

2月9日,30秒知全网,精选7个热点

///货拉拉将推出同城门到门跑腿服务 据介绍&#xff0c;两轮电动车将成为该业务的主要运力&#xff0c;预计将于3月中旬全面开放骑手注册和用户人气征集活动&#xff0c;并根据人气和线上骑手注册情况选择落地城市&#xff0c;于4月正式开放服务和骑手接单 ///三菱、乐天和莱茵…...

球面坐标系下的三重积分

涉及知识点 三重积分球面坐标系点火公式一些常见积分处理手法 球面坐标系定义 球面坐标系由方位角φ\varphiφ、仰角θ\thetaθ和距离rrr构成 直角坐标系(x,y,z)(x,y,z)(x,y,z)到球面坐标系的(r,φ,θ)(r,\varphi,\theta)(r,φ,θ)的转化规则如下&#xff1a; {xrsin⁡φco…...

谷歌 Jason Wei | AI 研究的 4 项基本技能

文章目录 一、前言二、主要内容三、总结CSDN 叶庭云:https://yetingyun.blog.csdn.net/ 一、前言 原文作者为 Jason Wei,2020 年达特茅斯学院本科毕业,之后加入 Google Brain 工作。 Jason Wei 的博客主页:https://www.jasonwei.net/ 其实我不算是一个特别有经验的研究员…...

excel数据整理:合并计算快速查看人员变动

相信大家平时在整理数据时&#xff0c;都会对比数据是否有重复的地方&#xff0c;或者该数据与源数据相比是否有增加或者减少。数据量不大还好&#xff0c;数据量大的话&#xff0c;对比就比较费劲了。接下来我们将进入数据对比系列课程的学习。该系列一共有两篇教程&#xff0…...

vit-pytorch实现 MobileViT注意力可视化

项目链接 https://github.com/lucidrains/vit-pytorch 注意一下参数设置&#xff1a; Parameters image_size: int. Image size. If you have rectangular images, make sure your image size is the maximum of the width and heightpatch_size: int. Number of patches. im…...

Python将字典转换为csv

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。喜欢通过博客创作的方式对所学的知识进行总结与归纳,不仅形成深入且独到的理…...

EasyX精准帧率控制打气球小游戏

&#x1f386;音乐分享 New Boy —— 房东的猫 之前都用Sleep&#xff08;&#xff09;来控制画面帧率&#xff0c;忽略了绘制画面的时间 如果绘制画面需要很长的时间&#xff0c;那么就不能忽略了。 并且Sleep&#xff08;&#xff09;函数也不是特别准确&#xff0c;那么就…...

你知道 GO 中什么情况会变量逃逸吗?

你知道 GO 中什么情况会变量逃逸吗&#xff1f;首先我们先来看看什么是变量逃逸 Go 语言将这个以前我们写 C/C 时候需要做的内存规划和分配&#xff0c;全部整合到了 GO 的编译器中&#xff0c;GO 中将这个称为 变量逃逸 GO 通过编译器分析代码的特征和代码的生命周期&#x…...

一篇文章学懂C++和指针与链表

指针 目录 指针 C的指针学习 指针的基本概念 指针变量的定义和使用 指针的所占的内存空间 空指针和野指针 const修饰指针 指针和数组 指针和函数 指针、数组、函数 接下来让我们开始进入学习吧&#xff01; C的指针学习 指针的基本概念 指针的作用&#xff1a;可…...

TPGS-cisplatin顺铂修饰维生素E聚乙二醇1000琥珀酸酯

TPGS-cisplatin顺铂修饰维生素E聚乙二醇1000琥珀酸酯(TPGS)溶于大部分有机溶剂,和水有很好的溶解性。 长期保存需要在-20℃,避光,干燥条件下存放&#xff0c;注意取用一定要干燥,避免频繁的溶解和冻干。 维生素E聚乙二醇琥珀酸酯(简称TPGS)是维生素E的水溶性衍生物,由维生素E…...

【20230206-0209】哈希表小结

哈希表一般哈希表都是用来快速判断一个元素是否出现在集合里。哈希函数哈希碰撞--解决方法&#xff1a;拉链法和线性探测法。拉链法&#xff1a;冲突的元素都被存储在链表中线性探测法&#xff1a;一定要保证tableSize大于dataSize&#xff0c;利用哈希表中的空位解决碰撞问题。…...

c++11 标准模板(STL)(std::multimap)(一)

定义于头文件 <map> template< class Key, class T, class Compare std::less<Key>, class Allocator std::allocator<std::pair<const Key, T> > > class multimap;(1)namespace pmr { template <class Key, class T…...

北京软件开发公司滕迎江/seo投放是什么意思

原文地址&#xff1a;http://blog.chinaunix.net/uid-7573623-id-2048961.htmllinux系统默认目录颜色是蓝色的&#xff0c;在黑背景下看不清楚&#xff0c;可以通过以下2种方法修改ls查看的颜色方法一&#xff1a;1、在~/.bash_profile文件中添加LS_COLORSexport LS_COLORSno00…...

万网域名网站建设/短视频获客系统

需求澄清用户友好的介绍 如果您不熟悉String格式或只想快速解决问题&#xff0c;那么String格式的Java文档不是最容易阅读和理解的。 尽管它很完整&#xff0c;但是它不是非常用户友好的&#xff0c;所以我想我会尝试编写一个更清晰的版本。 这篇文章不仅对您有帮助&#xff0c…...

绵阳专业网站建设/台州seo优化公司

第九章&#xff1a;转移指令的原理05 让编程改变世界 Change the world by program 实验八 分析一个奇怪的程序&#xff01;&#xff08;利用转移原理“玩”系统一下~&#xff09; 程序代码下载 实验九 根据材料编程(第一次——黑底白字下终于有了色彩&#xff01;) 程序代…...

公司找人做的网站到现在还没出来/搜索量查询百度指数

来源&#xff1a;blog.csdn.net/yasin_huang/article/details/106556935Spring-webflux简介什么是“响应式”Spring-webflux的响应式API选择Spring-webmvc还是Spring-webflux呢并发模型webflux代码示例Spring-webflux简介spring-webflux是spring在5.0版本后提供的一套响应式编程…...

商务科技网站建设/广州品牌营销服务

当时学习 Grunt 的时候&#xff0c;真是很头疼。分了两个时间段&#xff0c;学习了两次才硬啃下来&#xff0c;之后才能用在项目中。主要原因我认为是学习资料和文档上面写的太高端了。这类的文档或者资料有个显著特点&#xff0c;上来先简单介绍一下这个玩意&#xff08;Grunt…...

wordpress 列表样式/腾讯企业邮箱登录入口

异常&#xff1a;nested exception is org.apache.ibatis.binding.BindingException: Parameter testypid not found. Available parameters are [ztpsXmjcxx, pageable, param1, param2]分析&#xff1a;以为是xml文件中没有对应的字段&#xff0c;一细看了几遍是有这个字段的…...