【C++核心】C++中的对象

C++中的对象

  • 一、对象的初始化和清理
    • 1. 构造函数和析构函数
      • 1.1 构造函数简介
      • 1.2 构造函数
      • 1.3 析构函数
      • 1.4 代码样例
      • 1.5 默认实现
    • 2. 构造函数的分类及调用
      • 2.1 构造函数的分类
      • 2.2 构造函数的调用方式
      • 2.3 匿名函数
    • 3. 拷贝构造函数调用时机
    • 4. 构造函数的规则
    • 5. 深拷贝和浅拷贝
    • 6. 初始化列表
  • 二、类的成员
    • 1. 对象作为类的成员
    • 2. 静态成员
      • 2.1 静态成员变量
      • 2.2 静态成员函数
    • 3. this指针详解
      • 3.1 类的成员存储位置
      • 3.2 this指针
        • 3.2.1 this指针介绍
        • 3.2.2 this指针的用途
    • 4. 空指针访问成员函数
      • 4.1 空指针的使用
      • 4.2 个人理解
    • 5. const修饰成员函数
      • 5.1 常函数
      • 5.2 常对象
      • 5.3 示例

一、对象的初始化和清理

生活中我们买的电子产品都基本会有出厂设置,在某一天我们不用时候也会删除一些自己信息数据保证安全。C++中的面向对象来源于生活,每个对象也都会有初始设置以及对象销毁前的清理数据的设置。

1. 构造函数和析构函数

1.1 构造函数简介

对象的初始化和清理也是两个非常重要的安全问题​。一个对象或者变量没有初始状态,对其使用后果是未知;同样的,使用完一个对象或变量,没有及时清理,也会造成一定的安全问题。c++利用了构造函数和析构函数解决上述问题,这两个函数将会被编译器自动调用,完成对象初始化和清理工作。

1.2 构造函数

  1. 构造函数:主要作用在于创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无须手动调用。
  2. 构造函数语法:构造函数,没有返回值也不写void,函数名称与类名相同。构造函数可以有参数,因此可以发生重载。
     类名(){}
    
  3. 程序在调用对象时候会自动调用构造,无须手动调用,而且只会调用一次

1.3 析构函数

  1. 析构函数:主要作用在于对象销毁前系统自动调用,执行一些清理工作。
  2. 析构函数语法:析构函数,没有返回值也不写void,函数名称与类名相同,在名称前加上符号~。析构函数不可以有参数,因此不可以发生重载。
    ~类名(){}
    
  3. 程序在对象销毁前会自动调用析构,无须手动调用,而且只会调用一次

1.4 代码样例

class Person
{
public://构造函数Person() { cout << "Person的构造函数调用" << endl;} //析构函数~Person() {cout << "Person的析构函数调用" << endl;}
};void test01()
{ Person p; 
}int main() 
{test01();system("pause");return 0;
} 

1.5 默认实现

对象的初始化和清理工作是编译器强制要我们做的事情,因此如果我们不提供构造和析构,编译器会提供。编译器提供的构造函数和析构函数是空实现。

2. 构造函数的分类及调用

2.1 构造函数的分类

  1. 按参数分为: 有参构造和无参构造
  2. ​按类型分为: 普通构造和拷贝构造
//1、构造函数分类 
// 按照参数分类分为:有参和无参构造 无参又称为默认构造函数 
// 按照类型分类分为:普通构造和拷贝构造
class Person 
{
public: //无参(默认)构造函数 Person() { cout << "无参构造函数!" << endl; } //有参构造函数 Person(int a) { age = a; cout << "有参构造函数!" << endl;} //拷贝构造函数 Person(const Person& p) { age = p.age; cout << "拷贝构造函数!" << endl; } //析构函数 ~Person() { cout << "析构函数!" << endl; } 
public: int age; 
}

2.2 构造函数的调用方式

  1. 括号法:直接利用括号实现调用,注意调用无参构造函数不能加括号,如果加了编译器认为这是一个函数声明
    Person p();
    Person p1(10);
    //如下编译器会认为这个是一个返回值是Person类型、名称为p2的函数
    //Person p2();
    
  2. 显示法
    Person p2 = Person(10); 
    Person p3 = Person(p2);
    
  3. 隐式转换法
    Person p4 = 10; // Person p4 = Person(10); 
    Person p5 = p4; // Person p5 = Person(p4); 
    

2.3 匿名函数

当利用显示法进行调用时,不书写左值,单独写显示法调用,生成的就是匿名对象。匿名对象的当前行结束之后,会马上析构。注意,不能利用拷贝构造函数初始化匿名对象,编译器会自动把括号去掉,认为是对象声明。

//匿名函数
Person(10)
//Person(p3),编译器会转换为Person p3,此时,编译器只会认为声明了一个类型是Person,名字为p3的对象

3. 拷贝构造函数调用时机

C++中拷贝构造函数调用通常有三种情况:

class Person 
{ 
public: Person() { cout << "无参构造函数!" << endl; mAge = 0; } Person(int age) { cout << "有参构造函数!" << endl; mAge = age; } Person(const Person& p) { cout << "拷贝构造函数!" << endl; mAge = p.mAge; } //析构函数在释放内存之前调用 ~Person() { cout << "析构函数!" << endl; } 
public: int mAge; 
}
  1. 使用一个已经创建完毕的对象来初始化一个新对象
    void test01() {	Person man(100); //p对象已经创建完毕Person newman(man); //调用拷贝构造函数Person newman2 = man; //拷贝构造(构造器的隐式转换法)//Person newman3;//已经调用无参构造器创建了一个Person对象//newman3 = man; //不是调用拷贝构造函数,就是单纯的赋值操作,newman3的对象和man是一样的
    }
    
  2. 值传递的方式给函数参数传值
    //相当于Person p1 = p;
    void doWork(Person p1) {}
    void test02() {Person p; //无参构造函数doWork(p);
    }
    
  3. 以值方式返回局部对象
    Person doWork2()
    {Person p1;cout << (int *)&p1 << endl;return p1;
    }void test03()
    {Person p = doWork2();cout << (int *)&p << endl;
    }
    

4. 构造函数的规则

默认情况下,c++编译器至少给一个类添加3个函数

  1. 默认构造函数(无参,函数体为空)
  2. 默认析构函数(无参,函数体为空)
  3. 默认拷贝构造函数,对属性进行值拷贝

如果用户定义有参构造函数,C++不在提供默认无参构造,但是会提供默认拷贝构造。如果用户定义拷贝构造函数,C++不会再提供其他构造函数。

class Person {
public://无参(默认)构造函数Person() {cout << "无参构造函数!" << endl;}//有参构造函数Person(int a) {age = a;cout << "有参构造函数!" << endl;}//拷贝构造函数Person(const Person& p) {age = p.age;cout << "拷贝构造函数!" << endl;}//析构函数~Person() {cout << "析构函数!" << endl;}
public:int age;
};void test01()
{Person p1(18);//如果不写拷贝构造,编译器会自动添加拷贝构造,并且做浅拷贝操作Person p2(p1);cout << "p2的年龄为: " << p2.age << endl;
}void test02()
{//如果用户提供有参构造,编译器不会提供默认构造,会提供拷贝构造Person p1; //此时如果用户自己没有提供默认构造,会出错Person p2(10); //用户提供的有参Person p3(p2); //此时如果用户没有提供拷贝构造,编译器会提供//如果用户提供拷贝构造,编译器不会提供其他构造函数Person p4; //此时如果用户自己没有提供默认构造,会出错Person p5(10); //此时如果用户自己没有提供有参,会出错Person p6(p5); //用户自己提供拷贝构造
}

5. 深拷贝和浅拷贝

  1. 浅拷贝:简单的赋值拷贝操作
  2. 深拷贝:在堆区重新申请空间,进行拷贝操作
  3. 如果对象的某个成员变量为指向了堆区的某个空间的指针,此时浅拷贝操作只会拷贝空间的地址给新对象,而深拷贝则会在堆区创建一个相同的数据并将指向该空间的地址给新对象。
class Person {
public://无参(默认)构造函数Person() {cout << "无参构造函数!" << endl;}//有参构造函数Person(int age ,int height) {cout << "有参构造函数!" << endl;m_age = age;m_height = new int(height);}//拷贝构造函数  Person(const Person& p) {cout << "拷贝构造函数!" << endl;//如果不利用深拷贝在堆区创建新内存,会导致浅拷贝带来的重复释放堆区问题m_age = p.m_age;m_height = new int(*p.m_height);}//析构函数~Person() {cout << "析构函数!" << endl;if (m_height != NULL){delete m_height;}}
public:int m_age;int* m_height;
};void test01()
{Person p1(18, 180);Person p2(p1);cout << "p1的年龄: " << p1.m_age << " 身高: " << *p1.m_height << endl;cout << "p2的年龄: " << p2.m_age << " 身高: " << *p2.m_height << endl;
}

如果属性有在堆区开辟的,一定要自己提供拷贝构造函数,防止浅拷贝带来的问题

6. 初始化列表

C++提供了初始化列表语法,用来初始化属性,语法如下:

构造函数():属性1(1),属性2(值2... {}

距离:

class Person {
public:传统方式初始化//Person(int a, int b, int c) {//	m_A = a;//	m_B = b;//	m_C = c;//}//初始化列表方式初始化Person(int a, int b, int c) :m_A(a), m_B(b), m_C(c) {}void PrintPerson() {cout << "mA:" << m_A << endl;cout << "mB:" << m_B << endl;cout << "mC:" << m_C << endl;}
private:int m_A;int m_B;int m_C;
};int main() {Person p(1, 2, 3);p.PrintPerson();system("pause");return 0;
}

二、类的成员

1. 对象作为类的成员

C++类中的成员可以是另一个类的对象,我们称该成员为对象成员,如下即为B类中有对象A作为成员,A为对象成员:

class A {}
class B
{A a;
}

当创建B对象时,A比B先进行构造,即先调用对象成员的构造,再调用本类构造;当进行清理时,B比A先进行析构,即先调用本类的析构,再调用对象成员的析构。

class Phone
{
public:Phone(string name){m_PhoneName = name;cout << "Phone构造" << endl;}~Phone(){cout << "Phone析构" << endl;}string m_PhoneName;};class Person
{
public://初始化列表可以告诉编译器调用哪一个构造函数Person(string name, string pName) :m_Name(name), m_Phone(pName){cout << "Person构造" << endl;}~Person(){cout << "Person析构" << endl;}void playGame(){cout << m_Name << " 使用" << m_Phone.m_PhoneName << " 牌手机! " << endl;}string m_Name;Phone m_Phone;};
void test01()
{//当类中成员是其他类对象时,我们称该成员为 对象成员//构造的顺序是 :先调用对象成员的构造,再调用本类构造//析构顺序与构造相反Person p("张三" , "苹果X");p.playGame();}int main() {test01();system("pause");return 0;
}

2. 静态成员

静态成员就是在成员变量和成员函数前加上关键字static,称为静态成员静态成员分为静态成员变量和静态成员函数。

2.1 静态成员变量

对于静态成员变量,所有对象共享同一份数据,在编译阶段分配内存,且必须在类内声明,类外初始化。此外,静态成员变量也是有访问权限的。

静态成员变量有两种访问方式:通过对象例来访问和通过类名来访问。

class Person
{public:static int m_A; //静态成员变量//静态成员变量特点://1 在编译阶段分配内存//2 类内声明,类外初始化//3 所有对象共享同一份数据private://静态成员变量也是有访问权限的//类内声明static int m_B; 
};
//类外初始化
int Person::m_A = 10;
int Person::m_B = 10;void test01()
{//静态成员变量两种访问方式//1、通过对象Person p1;p1.m_A = 100;cout << "p1.m_A = " << p1.m_A << endl;Person p2;p2.m_A = 200;cout << "p1.m_A = " << p1.m_A << endl; //共享同一份数据cout << "p2.m_A = " << p2.m_A << endl;//2、通过类名cout << "m_A = " << Person::m_A << endl;//cout << "m_B = " << Person::m_B << endl; //私有权限访问不到
}int main() {test01();system("pause");return 0;
}

2.2 静态成员函数

对于静态成员函数,所有对象共享同一个函数,静态成员函数只能访问静态成员变量。此外,静态成员函数也是有访问权限的。

静态成员函数有两种访问方式:通过对象例来访问和通过类名来访问。

class Person
{public://静态成员函数特点://1 程序共享一个函数//2 静态成员函数只能访问静态成员变量static void func(){cout << "func调用" << endl;m_A = 100;//m_B = 100; //错误,不可以访问非静态成员变量,无法区分到底是哪个对象的成员变量}static int m_A; //静态成员变量int m_B; // 
private://静态成员函数也是有访问权限的static void func2(){cout << "func2调用" << endl;}
};
int Person::m_A = 10;void test01()
{//静态成员变量两种访问方式//1、通过对象Person p1;p1.func();//2、通过类名Person::func();//Person::func2(); //私有权限访问不到
}int main() {test01();system("pause");return 0;
}

3. this指针详解

3.1 类的成员存储位置

  1. 在C++中,类内的成员变量和成员函数分开存储。
  2. 只有非静态成员变量才在对象上,类的静态成员变量、类的静态成员函数、类的非静态成员函数都不在对象上,都只有一份。
class Person {
public:Person() {mA = 0;}//非静态成员变量占对象空间int mA;//静态成员变量不占对象空间static int mB; //函数也不占对象空间,所有函数共享一个函数实例void func() {cout << "mA:" << this->mA << endl;}//静态成员函数也不占对象空间static void sfunc() {}
};int main() {cout << sizeof(Person) << endl;system("pause");return 0;
}

3.2 this指针

3.2.1 this指针介绍

C++中每一个非静态成员函数只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码,那么这一块代码是如何区分那个对象调用自己的呢?C++通过提供特殊的对象指针【this指针】,解决上述问题。this指针指向被调用的【成员函数】所属的对象

this指针是隐含每一个非静态成员函数内的一种指针;它不需要定义,直接使用即可,实际上在非静态成员函数的参数列表里,编译器为我们自动加上了this指针。

3.2.2 this指针的用途
  1. 形参和成员变量同名时,可用this指针来区分
  2. 在类的非静态成员函数中返回对象本身,可使用return *this
  3. 通常情况下,C++的函数中调用到的成员变量都会默认加上this指针
class Person
{
public:Person(int age){//1、当形参和成员变量同名时,可用this指针来区分this->age = age;}Person& PersonAddPerson(Person p){this->age += p.age;//返回对象本身return *this;}int age;
};void test01()
{Person p1(10);cout << "p1.age = " << p1.age << endl;Person p2(10);p2.PersonAddPerson(p1).PersonAddPerson(p1).PersonAddPerson(p1);cout << "p2.age = " << p2.age << endl;
}int main() {test01();system("pause");return 0;
}

4. 空指针访问成员函数

4.1 空指针的使用

C++中空指针也是可以调用成员函数的,但是也要注意有没有用到this指针。如果用到this指针,需要加以判断保证代码的健壮性。

//空指针访问成员函数
class Person {
public:void ShowClassName() {cout << "我是Person类!" << endl;}void ShowPerson() {if (this == NULL) {return;}cout << mAge << endl;}public:int mAge;
};void test01()
{Person * p = NULL;p->ShowClassName(); //空指针,可以调用成员函数p->ShowPerson();  //但是如果成员函数中用到了this指针,就不可以了
}int main() {test01();system("pause");return 0;
}

4.2 个人理解

class Person 
{
public:int* content;string name;static int num;
public:Person() {name = "nihao";}Person(int* c_content, string n_name) {content = c_content;name = n_name;}Person(const Person& p) {content = new int(*p.content);name = p.name;cout << "Person类的拷贝构造器调用" << endl;}~Person() {}public:void print_name() {cout << name << endl;}void print1() {cout << 1 << endl;}void print2() {this->print1();}
};int Person::num = 10;int main()
{int* point = new int(5);string name = "hello";Person p(point, name);p.print_name();Person* pnull = NULL;//属性不允许,会报错//pnull->print_name();//方法允许,可运行pnull->print2();cin.get();
}

当利用空指针进行成员函数的调用时发现:

  1. 如果该函数内部调用了this->成员变量(this编译器会默认加上),会报错无法运行。
  2. 如果该函数内部显式调用了this->其他成员函数,则可以正常运行

个人理解:this指向的是调用该成员函数的对象,对象是空指针。成员变量存在于对象上,所以无法访问成员变量,出错;函数存在于对象之外,所以可以访问,正常运行

5. const修饰成员函数

5.1 常函数

成员函数后加const后我们称为这个函数为常函数;函数内不可以修改成员属性;但是,如果成员属性声明时加关键字mutable后,在常函数中依然可以修改该成员属性。

实际上,这跟this指针有关,this指针的本质是一个指向常量的指针,指针的指向不可修改如果想让指针指向的值也不可以修改,需要声明常函数,表明此时的指针式一个指向常量的指针常量。此时,指针的声明从Person* const this变为了const Person* const this

5.2 常对象

声明对象前加const称该对象为常对象;常对象只能调用常函数。

5.3 示例

class Person 
{
public:Person() {m_A = 0;m_B = 0;}//this指针的本质是一个指针常量,指针的指向不可修改//如果想让指针指向的值也不可以修改,需要声明常函数void ShowPerson() const {//const Type* const pointer;//this = NULL; //不能修改指针的指向 Person* const this;//this->mA = 100; //但是this指针指向的对象的数据是可以修改的//const修饰成员函数,表示指针指向的内存空间的数据不能修改,除了mutable修饰的变量this->m_B = 100;}void MyFunc() {mA = 10000;}public:int m_A;mutable int m_B; //可修改 可变的
};//const修饰对象  常对象
void test01() {const Person person; //常量对象  cout << person.m_A << endl;//person.mA = 100; //常对象不能修改成员变量的值,但是可以访问person.m_B = 100; //但是常对象可以修改mutable修饰成员变量//常对象访问成员函数person.MyFunc(); //常对象不能调用非const的函数,因为非const的函数可以修改成员变量}int main() {test01();system("pause");return 0;
}

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

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

相关文章

ChatGLM3初体验

mac本地化部署ChatGLM3 写在前面环境准备1. python环境2. 安装第三方依赖torch3.下载模型 代码准备1.clone代码 run效果 写在前面 建议直接去看官方文档 https://github.com/THUDM/ChatGLM3?tabreadme-ov-file 环境准备 1. python环境 python -V ## 3.11.42. 安装第三方依…

标注平台工作流:如何提高训练数据质量与管理效率

世界发展日益依托数据的驱动&#xff0c;企业发现&#xff0c;管理不断增长的数据集却愈发困难。数据标注是诸多行业的一个关键过程&#xff0c;其中包括机器学习、计算机视觉和自然语言处理。对于大型语言模型&#xff08;LLM&#xff09;来说尤是如此&#xff0c;大型语言模型…

前端面试问题汇总 - Vue篇

1. Vue 的生命周期有哪些&#xff0c;每个阶段分别做什么操作&#xff1f; beforeCreate&#xff1a; 在实例初始化之后、数据观测和事件配置之前被调用。此时数据对象 data 和事件&#xff08;methods&#xff09;都还未初始化。一般不在此阶段进行数据初始化和 DOM 操作。cre…

为什么我们应该切换到Rust

What is RUST? 什么是Rust&#xff1f; Rust is a programming language focused on safety, particularly safe concurrency, supporting functional and imperative-procedural paradigms. Rust is syntactically similar to C, but it provides memory safety without usi…

[大模型]Yi-6B-chat WebDemo 部署

Yi-6B-chat WebDemo 部署 Yi 介绍 由60亿个参数组成的高级语言模型 Yi LLM。为了促进研究&#xff0c;Yi 已经为研究社区开放了Yi LLM 6B/34B Base 和 Yi LLM 6B/34B Chat。 环境准备 在autodl平台中租一个3090等24G显存的显卡机器&#xff0c;如下图所示镜像选择PyTorch–…

leecode438 | 找到所有字符串中的异位词

题意大致是&#xff0c;给定两个字符串&#xff0c;s 和 p 其中 要在s 中找到由p的元素组成的子字符串&#xff0c;记录子字符串首地址 class Solution { public:vector<int> findAnagrams(string s, string p) {int m s.size(), n p.size();if(m < n)return {};vec…

vue-router 原理【详解】hash模式 vs H5 history 模式

hash 模式 【推荐】 路由效果 在不刷新页面的前提下&#xff0c;根据 URL 中的 hash 值&#xff0c;渲染对应的页面 http://test.com/#/login 登录页http://test.com/#/index 首页 核心API – window.onhashchange 监听 hash 的变化&#xff0c;触发视图更新 window.onhas…

谷歌关键词优化全攻略提高曝光率-华媒舍

现如今&#xff0c;互联网已成为信息获取的主要渠道&#xff0c;而搜索引擎则是人们寻找信息的首选工具之一。其中&#xff0c;谷歌作为全球最大的搜索引擎&#xff0c;其搜索结果的排名直接影响着网站的曝光率和流量。了解并掌握谷歌关键词优化的技巧&#xff0c;成为提升网站…

Vue项目打包:禁止生成sourceMap文件

Vue项目在打包过程中&#xff0c;默认会生成sourceMap文件。 sourceMap的主要作用是让打包后的文件像未压缩的代码一样&#xff0c;方便调试和定位错误。然而&#xff0c;在生产环境中我们通常不需要这些文件&#xff0c;因为它们会增加应用程序的体积。 可以在vue.config.js…

MySQL-多表查询:多表查询分类、SQL99语法实现多表查询、UNION的使用、7种SQL JOINS的实现、SQL99语法新特性、多表查询SQL练习

多表查询 1. 一个案例引发的多表连接1.1 案例说明1.2 笛卡尔积&#xff08;或交叉连接&#xff09;的理解1.3 案例分析与问题解决 2. 多表查询分类讲解分类1&#xff1a;等值连接 vs 非等值连接等值连接非等值连接 分类2&#xff1a;自连接 vs 非自连接分类3&#xff1a;内连接…

团结引擎+OpenHarmony 1配置篇

团结引擎OpenHarmony 1 配置篇 app团结鸿蒙化第一课一 DevEco Studio 下载安装二 团结引擎三 出包 app团结鸿蒙化第一课 1 团结引擎配置2 DevEco Studio 配置 一 DevEco Studio 下载安装 申请开发者套件 1 注册华为账号 签署协议 官网 2 认真填写 DevEco Studio 开发套件申请…

高清4路HDMI编码器JR-3214HD

产品简介&#xff1a; JR-3214HD四路高清HDMI编码器是专业的高清音视频编码产品&#xff0c;该产品具有支持4路高清HDMI音视频采集功能&#xff0c;4路3.5MM独立外接音频输入&#xff0c;编码输出双码流H.264格式&#xff0c;音频MP3/AAC格式。编码码率可调&#xff0c;画面质…

预约系统的使用

预约系统的使用 目录概述需求&#xff1a; 设计思路实现思路分析1.用户年规则 在 预约系统中的使用流程 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better result,wa…

【LeetCode热题100】【二叉树】路径总和 III

题目链接&#xff1a;437. 路径总和 III - 力扣&#xff08;LeetCode&#xff09; 要从上到下找一条路径的和最简单的方法是遍历每个节点&#xff0c;然后从每个节点往下累加看看和对不对 这样是O(n&#xff09;的时间复杂度 可以计算一条路径上的前缀和方法&#xff0c;这样…

[图像处理] MFC OnMouseMove()绘制ROI矩形时的闪烁问题

文章目录 问题对策代码完整工程 结果使用Picture控件的RedrawWindow()的效果使用Dialog的RedrawWindow()的效果使用Picture控件的RedrawWindow()&#xff0c;ROI绘制到图像外的效果 结论 问题 最近想通过业余时间&#xff0c;写一个简单的图像处理软件&#xff0c;一点点学习图…

测试计划和测试报告

1、软件测试计划简介 测试计划&#xff0c;一般是主管写&#xff0c;在需求分析之后&#xff0c;测试工作开始之间做的一些准备划工作。一般包含以下内容&#xff1a;5W1H 目的、测试范围、测试进度安排、测试人员、测试环境、测试方法工具&#xff0c;风险评估 &#xff08;w…

redis知识整理

redis知识整理 什么是缓存穿透&#xff0c;怎么解决布隆过滤器 什么是缓存击穿&#xff0c;怎么解决互斥锁和分布式锁 什么是缓存雪崩&#xff0c;怎么解决Redis作为缓存&#xff0c;mysql如何与redis进行同步呢&#xff1f;&#xff08;双写一致&#xff09;一致性要求高排他锁…

如何在 MySQL 中开启日志记录并排查操作记录

在数据库管理中&#xff0c;能够追踪和审查操作记录是至关重要的。这不仅有助于识别和分析正常的数据库活动&#xff0c;还可以在数据泄露或未经授权的更改发生时进行调查和响应。本文将介绍如何在 MySQL 中开启通用日志记录&#xff0c;并如何排查操作记录。 开启 MySQL 通用…

2024/4/14周报

文章目录 摘要Abstract文献阅读题目创新点CROSSFORMER架构跨尺度嵌入层&#xff08;CEL&#xff09;CROSSFORMER BLOCK长短距离注意&#xff08;LSDA&#xff09;动态位置偏置&#xff08;DPB&#xff09; 实验 深度学习CrossFormer背景维度分段嵌入&#xff08;DSW&#xff09…

c++ 根据ip主机号和子网掩码随机生成ip

在C中&#xff0c;可以使用以下方法根据给定的IP地址和子网掩码来随机生成IP地址。这里使用了库来生成随机数&#xff0c;以及<arpa/inet.h>库来处理IP地址。 #include <iostream> #include <random> #include <arpa/inet.h>std::string random_ip(co…