无锡网站建设电话/网站seo平台

无锡网站建设电话,网站seo平台,珠海网站建设解决方案,安徽省做网站目录 一.inline内联的详细介绍 (1)为什么在调用内联函数时不需要建立栈帧: (2)为什么inline声明和定义分离到两个文件会产生链接错误,链接是什么,为什么没有函数地址: 二.类&…

目录

一.inline内联的详细介绍

(1)为什么在调用内联函数时不需要建立栈帧:

(2)为什么inline声明和定义分离到两个文件会产生链接错误,链接是什么,为什么没有函数地址:

二.类,实例化和this指针

1.类的介绍(class):

2.实例化:

(1)实例化的概念:

(2)实例化的空间分配:

3.this指针:

4.关于空指针访问成员变量的注意点:

三.类的默认成员函数

1.构造函数:

2.析构函数:

3.拷贝构造函数:

4.运算符重载:

四.日期类实现

一.inline内联的详细介绍

为了更清楚的明白类的定义与底层运行逻辑,我先从inline内联开始讲起:

• ⽤inline修饰的函数叫做内联函数编译时C++编译器会在调用的地方展开内联函数,这样调用内联函数就不需要建立栈帧了,就可以提高效率 //(1)为什么不需要建立栈帧

• inline对于编译器⽽⾔只是⼀个建议,也就是说,你加了inline编译器也可以选择在调⽤的地方不展开,不同编译器关于inline什么情况展开各不相同,因为C++标准没有规定,inline适用于频繁调⽤的短⼩函数,对于递归函数,代码相对多⼀些的函数,加上inline也会被编译器忽略(因为内联的展开在需要频繁调用短小函数的代码里,可以大限度上减少函数调用指令(call)的使用,而在其他函数体本身较大的情况下,inline不展开的调用指令的方法可能会显得更为简便) 

• C语言实现宏函数也会在预处理时替换展开,但是宏函数实现很复杂很容易出错的,且不⽅便调 试,C++设计了inline⽬的就是替代C的宏函数

• vs编译器debug版本下⾯默认是不展开inline的,这样方便调试

• inline不建议声明和定义分离到两个⽂件,分离会导致链接错误。因为inline被展开,就没有函数地址,链接时会出现报错//(2)为什么会产生链接错误,链接是什么,为什么没有函数地址

(内联的使用示例)

#include <iostream>// 显式声明为内联函数
inline int add(int a, int b) {return a + b;
}int main() {std::cout << add(3, 5) << std::endl; // 编译器可能将 add(3,5) 展开为 `3 + 5`return 0;
}

上述的阐述乍看总有种似懂非懂的感觉,但一旦深入想想就还有好些东西不明不白,下面我将对这段话中可能会产生的疑问做出一一解答:

(1)为什么在调用内联函数时不需要建立栈帧:

(a).在理解这个问题之前,我们需要先搞明白函数的栈帧是怎么一回事

       简而言之栈帧是程序执行过程中用于保存函数调用状态的临时数据结构,它在函数调用时被创建,返回时销毁。每个栈帧对应一次函数调用,记录了函数的执行上下文信息

以下这张图片就展示了函数Add在调用时所创建的栈帧,而其中的push等相关汇编命令我也附在下面:

        

(b).再让我们区别以下函数的栈帧整体代码的编译和链接的关系:

据上述代码编译的过程而言,函数栈帧的创建属于程序运行时的动态数据结构,虽与编译链接过程的静态代码无关,但编译与链接依旧会在其运行时对其产生影响:如编译阶段为栈帧的创建和销毁生成正确的指令,以及链接阶段确定函数的位置以及符号引用,因此,一般情况下较小的函数被inline展开时,其函数名并不会进入符号表,而是直接在调用处替换代码(发生在预处理中,编译之前),自然也就跟栈帧的创建销毁没啥关系了

(2)为什么inline声明和定义分离到两个文件会产生链接错误,链接是什么,为什么没有函数地址:

  

inline之所以不建议声明定义分离,是因为当我们假设在head.h头文件里定义了内联函数add(自定义函数名)然后分别在a.cpp里定义add函数然后在b.cpp里调用add函数然后运行,那么在对程序进行编译时,会发现对于add函数头文件里只有声明而没有定义,因此编译器会假设add为一个外部函数(这里类似于一般函数的跨文件调用),但与一般函数调用不同的是,一般函数在假设外部函数时会同时在符号表生成一个对函数的引用(包含了未解析的地址),然后再在链接过程中通过对各文件的链接重新补全符号表里未解析的地址,从而实现函数声明定义的分开,但inline函数却不一样,它同样会在符号表里生成一个未解析的地址,但由于inline函数的性质就是对函数体代码的整体替换从而实现对指令代码的节约使用而且需要明确的内联点才可以进行替换,因此这样导致了其无法在链接时找到对应的内联点进而不能像一般函数那样在链接过程中补全对应的符号表里未解析的地址(内联需要替换的代码都找不到更别说地址了),从而发生链接的报错

二.类,实例化和this指针

1.类的介绍(class):

其中有两点需要特别注意

(a) 类中的成员函数默认为内联

(b)关于访问限定符:

如下代码:public和private是访问限定符,在public后面的成员函数和成员变量可以直接在类的外部使用,private后面的成员函数和成员变量不能被直接使用。       

        通常我们把成员函数定义为public,把成员变量定义为private

#include<iostream>
using namespace std;
class TEST
{
public://成员函数void test(){return;}
private://成员变量int _a;int _b;
};
//以上class为类的关键字,TEST为类的名字,{}中的为类的主体//但同样的,C++由于相当于C的pro max版,同时也可以兼容C中的struct结构:
typedef struct ListNodeC
{struct ListNodeC* next;int val;
}LTNode;int main()
{return 0;
}

关于类域

#include<iostream>
using namespace std;class TEST
{
public://成员函数声明int test(int a, int b);private://成员变量int _a;int _b;
};
//类定义了一个新的作用域,类的所有成员函数都在类的作用域中。在类体外定义成员时,需要使用类域名::来访问成员
//如果不指定类域的话,在定义函数时,程序在全局域找不到函数的声明就会报错。编译器不会主动去类域中寻找函数定义
int TEST::test(int a, int b)
{return a + b;
}
int main()
{TEST A;int c = 10; int d = 20;cout << A.test(c, d) << endl;return 0;
}

2.实例化:

(1)实例化的概念:

(2)实例化的空间分配:

 对象的大小只包含成员变量的大小,成员函数不占内存空间

打个比方,现在实例化出了两个类,分别为A,B但A和B的成员变量和地址是不同的,但如果访问这两个类的成员函数,他们都会链接到一个地址(只读存储区,静态存储),所以说我们sizeof(类对象)只用统计成员变量占用的空间

 成员变量占用的空间也符合内存对齐规则:

关于这个对齐其实有点比较容易遗忘,因此我再简述一下:

1. 基本概念
 对齐:数据类型的起始地址必须是该类型大小的整数倍
 例如: int (4字节)的地址必须是  0x4, 0x8, 0xC... 
 未对齐:数据起始地址不满足对齐规则,可能导致性能下降或硬件错误(如 ARM 架构)

2. 内存对齐规则
 a. 自然对齐
 规则:每个数据类型的地址必须是其自身大小的整数倍
 示例:

struct AlignedStruct {char a;        // 1字节 → 地址 0x0int b;        // 4字节 → 地址 0x4(填充3字节)double c;     // 8字节 → 地址 0x8(填充7字节)
};

b. 结构体对齐
成员顺序:成员按声明顺序排列,每个成员按自然对齐对齐

举例:

​
struct CompactStruct {int a;       // 0x0char b;      // 0x4(填充3字节)short c;     // 0x8
}; // 总大小:12字节(而非 16字节)​

3.this指针:

• Date类中有Init与Print两个成员函数,函数体中没有关于不同对象的区分,那当d1调⽤Init和 Print函数时,该函数是如何知道应该访问的是d1对象还是d2对象呢?那么这⾥就要看到C++给了 ⼀个隐含的this指针解决这⾥的问题

• 编译器编译后,类的成员函数默认都会在形参第⼀个位置,增加⼀个当前类类型的指针,叫做this 指针。⽐如Date类的Init的真实原型为, void Init(Date* const this, int year, int month, int day)

• 类的成员函数中访问成员变量,本质都是通过this指针访问的,如Init函数中给_year赋值, this- >_year = year;

• C++规定不能在实参和形参的位置显示的写this指针(编译时编译器会处理),但是可以在函数体内显示使⽤this指针

 另外需要注意一点,this指针其实存放在栈区,而不是对象里面

#include<iostream>
using namespace std;
class Date
{
public:// void Init(Date* const this, int year, int month, int day)void Init(int year, int month, int day){// this->_year = year;_year = year;this->_month = month;this->_day = day;}void Print(){cout << _year << "/" << _month << "/" << _day << endl;}
private:// 这⾥只是声明,没有开空间 int _year;int _month;int _day;
};int main()
{Date A;return 0;
}//成员函数在传参时都有一个类的指针类型的this指针,这个this指针编译器不会显示出来,但实际上他是存在的,看上边这串代码,如果再函数调用赋值的时候,可以手动把this指针加上去,这样其实并不会报错。这就说明这个this指针是真实存在的

4.关于空指针访问成员变量的注意点:

先看一下下面这两个代码:

       这两串代码运行的结果并不相同,已知第一个是正常运行,第二个是运行崩溃,首先我们应该知道不管是C语言中还是C++中,解引用空指针并不会编译报错,只会运行崩溃

其次再来分析问什么第二个是运行崩溃

        首先成员函数不会占用物理内存,只有成员变量会,实例出nullptr说明没开空间,但仔细看第一个程序是不需要访问成员变量的,所以不开空间也没有报错,而第二个程序访问了开空间的成员变量:_a,所以运行崩溃了

三.类的默认成员函数

默认成员函数就是⽤⼾没有显式实现,编译器会⾃动⽣成的成员函数称为默认成员函数:

接下来我会对其中的几个做出详细介绍:

1.构造函数:

       构造函数也是一种成员函数但他和我们写的普通构造函数不同的是,他是在我们实例化类的对象是默认调用的,也就是说,实例化对象是他自己会去主动调用这个构造函数,其本质是要替代我们以前Stack和Date类中写的Init函数的功能,构造函数⾃动调⽤的 特点就完美的替代的了Init

接下来说说它的基本特点

函数名和类名相同;

没有返回值:

#include<iostream>
using namespace std;
class DATE
{
public:DATE(int year = 2000, int mouth = 11, int day = 1){_year = year;_mouth = mouth;_day = day;}
private://成员函数//private成员函数不能直接访问,可以通过成员函数访问int _year;int _mouth;int _day;
};
int main()
{DATE d1;return 0;
}//上面这串代码中定义了一个日期类,并实例化出一个对象d1,调试可以看到,实例化d1自动调用了DATE这个构造函数,给d1的三个成员变量进行了赋值//构造函数也有很多种,第一种无参构造函数。第二种是全缺省构造函数,第三种就是不写构造时编译器默认的构造函数(接下来我会具体说说这三种函数),如果我们在实例化的时候只写这个对象就像上面这串代码这样:DATE d1; 这样调用的构造函数叫默认构造

       

//无参构造函数
DATE()
{_year = 1;_mouth = 1;_day = 1;
}//全缺省构造函数
DATE(int year = 2000, int mouth = 11, int day = 1)
{_year = year;_mouth = mouth;_day = day;
}// 带参构造函数 
Date(int year, int month, int day)
{_year = year;_month = month;_day = day;
}

       除了以上几点还有一点需要额外注意:如果类中没有显式定义构造函数,则C++编译器会⾃动⽣成⼀个⽆参的默认构造函数,⼀旦用户显式定义编译器将不再⽣成,也就是说我们不写,编译器默认⽣成的构造,对内置类型成员变量的初始化没有要求,也就是说是是否初始化是不确定的,看编译器。对于⾃定义类型成员变量,要求调⽤这个成员变量的默认构造函数初始化,  如果这个成员变量,没有默认构造函数,那么就会报错,我们要初始化这个成员变量,需要⽤初始化列表才能解决,初始化列表的问题,本文先放一下,下一篇文章再作详细介绍

       读到这里,会发现一个问题就是既然系统会自动生成默认构造函数,那为什么我们还需要自己去写构造函数?举个例子:

当类需要动态分配内存(如 new  或 malloc )时,默认构造函数无法自动释放资源,必须手动管理:

class Buffer {
public:int* data; // 动态内存// 自定义构造函数:初始化 dataBuffer(int size) : data(new int[size]) {std::cout << "Buffer initialized with size " << size << std::endl;}// 析构函数:释放资源~Buffer() {delete[] data;std::cout << "Buffer destroyed" << std::endl;}
};int main() {Buffer buf(1024); // 调用自定义构造函数return 0;
}

默认构造函数不会初始化 data ,导致未定义行为(如悬空指针),自定义构造函数确保 data 正确分配内存

2.析构函数:

       析构函数可以在类对象销毁时自动调用,释放我们的内存空间。就好比之前实现的栈这个数据结构,我们需要把我们malloc出来的空间都free掉,那么这个时候如果是使用c++里面的类来完成的话,在我们的栈销毁时(该对象生命周期结束时)就可以自动调用析构函数释放内存


~Stack()
{cout << "~Stack()" << endl;free(_a);_a = nullptr;_top = _capacity = 0;
}

析构的特点也很明显:

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

2.不需要写返回值

3.和构造函数一样,我们不写编译器⾃动⽣成的析构函数对内置类型成员不做处理,⾃定类型成员会调⽤他的析构函数

4.一个类只有一个析构且当类成员不需要释放空间时,不需要自己写析构函数

#include<iostream>
using namespace std;
typedef int STDataType;
class Stack
{
public:Stack(int n = 4){_a = (STDataType*)malloc(sizeof(STDataType) * n);if (nullptr == _a){perror("malloc申请空间失败");return;}_capacity = n;_top = 0;}~Stack(){cout << "~Stack()" << endl;free(_a);_a = nullptr;_top = _capacity = 0;}
private:STDataType* _a;size_t _capacity;size_t _top;
};

3.拷贝构造函数:

如果⼀个构造函数的第⼀个参数是⾃⾝类类型的引⽤,且任何额外的参数都有默认值,则此构造函数 也叫做拷贝构造函数,也就是说拷贝构造是⼀个特殊的构造函数

#include<iostream>
using namespace std;class DATE
{
public:DATE(int year, int mouth, int day){_year = year;_mouth = mouth;_day = day;}void Print(){cout << _year << "年" << _mouth << "月" << _day << "日" << endl;}
private://成员函数//private成员函数不能直接访问,可以通过成员函数访问int _year;int _mouth;int _day;
};
int main()
{DATE d1(10,10,10);DATE d2(d1);//调用拷贝构造d1.Print();d2.Print();return 0;
}
//注意,第一个参数必须是引用。否则编译器会报错。为什么会报错呢?理解一下,如果说我们传入的第一个参数没有引用,那么这个形参是得拷贝一份我们的实参,怎么拷贝呢?他还是得调用我们的拷贝构造函数去拷贝,那这就形成了闭环,而这样无限拷贝下去编译器是不允许的//对于没有主动写拷贝构造的类,编译器也会默认生成一个拷贝构造,对于内置类型进行浅拷贝,也就是只拷贝值,对于自定义类型成员会调用他的拷贝构造。

但还有几点需要注意:

1.像Date这样的类成员变量全是内置类型且没有指向什么资源,编译器⾃动⽣成的拷⻉构造就可以完 成需要的拷⻉,所以不需要我们显⽰实现拷⻉构造,但像Stack这样的类,虽然也都是内置类型,但 是_a指向了资源,编译器⾃动⽣成的拷⻉构造完成的值拷⻉/浅拷⻉不符合我们的需求,所以需要我们⾃⼰实现深拷⻉(对指向的资源也进⾏拷⻉),像MyQueue这样的类型内部主要是⾃定义类型 Stack成员,编译器⾃动⽣成的拷⻉构造会调⽤Stack的拷⻉构造,也不需要我们显⽰实现 MyQueue的拷⻉构造(前提是Stack这个类有析构)

2.传值返回会产⽣⼀个临时对象调⽤拷⻉构造传值引⽤返回,返回的是返回对象的别名(引⽤),没有产⽣拷⻉。但是如果返回对象是⼀个当前函数局部域的局部对象,函数结束就销毁了,那么使⽤ 引⽤返回是有问题的,这时的引⽤相当于⼀个野引⽤,类似⼀个野指针⼀样。传引⽤返回可以减少拷⻉,但是⼀定要确保返回对象在当前函数结束后还在,才能⽤引⽤返回

4.运算符重载:

运算符重载简而言之就是赋予我们常见的运算符以新的定义与使用场景,比如+号原来只可以用于数字之间的运算,但经过运算符重载之后,使其可以进行日期之间的计算,诸如此类:

bool operator==(DATE x)
{return _year == x._year && _mouth == x._mouth && _day == x._day;
}

以下是几个注意点:

1.不能对c++没有的符号进行重载

2、以下五个运算符不能进行重载:

.*      ::      sizeof       ? :       .

3.运算符重载的参数列表至少要含有一个自定义类型,不能通过运算符重载改变内置类型对象的含义,如: int operator+(int x, int y)

4.重载++运算符时,有前置++和后置++,运算符重载函数名都是operator++,无法很好的区分。 C++规定,后置++重载时,增加⼀个int形参,跟前置++构成函数重载,方便区分

四.日期类实现

//Date.h
#pragma once
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
class DATE
{
public:DATE(int year = 2000, int mouth = 11, int day = 1){_year = year;_mouth = mouth;_day = day;}//短小多次调用函数使用inline//clase默认inlineint GetMouthDay(int year, int mouth){assert(mouth > 0 && mouth < 13);static int mouthDayArray[13] = { -1,31,28,31,30,31,30,31,31,30,31,30,31 };//多次访问直接定义静态数组if (mouth == 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0))//让容易不通过的条件放前面{return 29;}else return mouthDayArray[mouth];}DATE& operator+=(int day);//声明运算符重载DATE& operator+(int day);void Print(){cout << _year << "年" << _mouth << "月" << _day << "日" << endl;}//日期比较bool operator>(DATE x){if (_year > x._year) return true;else if (_year < x._year) return false;if (_mouth > x._mouth) return true;else if (_mouth < x._mouth) return false;if (_day > x._day) return true;else return false;}bool operator==(DATE x){return _year == x._year && _mouth == x._mouth && _day == x._day;}bool operator < (DATE x){return !(*this > x) && !(*this == x);}bool operator!=(DATE& d2){return !(*this == d2);}DATE operator++(int){//后置加加返回原值//注意这个临时变量出了这个函数就销毁了所以不能引用返回DATE tmp(*this);_day++;if (_day > GetMouthDay(_year, _mouth)){_day = 1; _mouth++;}if (_mouth > 12){_year++;_mouth = 1;}return tmp;}//两日期相减int operator-(DATE& d1);
private://成员函数//private成员函数不能直接访问,可以通过成员函数访问int _year;int _mouth;int _day;
};
//text.cpp#include"DATE.h"DATE& DATE::operator+=(int day)//表明所属类
{//由于更改了自身所以重载的是+=//引用返回可以避免拷贝,节省开销//不能返回空值,不然无法解决这种问题(a+=10)+=10//对于这种情况如果传dATE返回的话也无法改变原值,不符合预期。_day += day;while (_day > GetMouthDay(_year, _mouth)){_day -= GetMouthDay(_year, _mouth);++_mouth;if (_mouth == 13){_year++;_mouth = 1;}}return *this;
}
DATE& DATE::operator+(int day)
{//DATE tmp(*this);//拷贝//默认构造函数DATE tmp = *this;///同样也是调用默认构造函数tmp += day;return tmp;
}
int DATE::operator-(DATE& d1)
{int cnt = 0;int flag = 1;DATE max = *this;DATE min = d1;if (max < min){flag = -1;max = d1;min = *this;}while (max != min){cnt++;min++;}return cnt * flag;
}

以上就是关于日期类相关的函数代码了

欧克,时间也不晚了,就到这里吧

全文终

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

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

相关文章

四种 No-SQL

在一个常规的互联网服务中&#xff0c;读取与写入的比例大约是 100:1 到 1000:1。然而&#xff0c;从硬盘读取时&#xff0c;数据库连接操作耗时&#xff0c;99% 的时间花费在磁盘寻址上。 为了优化读取性能&#xff0c;非规范化的设计通过添加冗余数据或分组数据来引入。下述…

【 Manus平替开源项目】

文章目录 Manus平替开源项目1 OpenManus1.1 简介1.2 安装教程1.3 运行 2 OWL2.1 简介2.2 安装教程2.3 运行 3 OpenHands&#xff08;原OpenDevin&#xff09;3.1 简介3.2 安装教程和运行 Manus平替开源项目 1 OpenManus 1.1 简介 开发团队: MetaGPT 核心贡献者&#xff08;5…

【Linux 服务之ollama 部署过慢问题】

特别慢的 curl -fsSL https://ollama.com/install.sh | sh参考 方法1 export OLLAMA_MIRROR"https://ghproxy.cn/https://github.com/ollama/ollama/releases/latest/download" curl -fsSL https://ollama.com/install.sh | sed "s|https://ollama.com/downl…

疗养院管理系统设计与实现(代码+数据库+LW)

摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装疗养院管理系统软件来发挥其高效地信息处理的作用&#xf…

Web后端开发之Maven

Maven Mven是apache旗下的一个开源项目&#xff0c;用来管理和构建java项目的工具。 通过一小段描述信息来管理项目。 Maven的作用 1.依赖管理&#xff1a;方便快捷的管理项目依赖的资源&#xff08;jar包&#xff09;&#xff0c;避免版本冲突问题 以前用某个jar包需要下载…

Linux文件IO——缓冲区磁盘上的文件管理

前言 什么是缓冲区&#xff1f; 缓冲区是内存空间上的一小段内存&#xff0c;我们平常在写程序的时候&#xff0c;其实是很难感知到缓冲区的存在的&#xff0c;接下来看一段代码&#xff0c;可以很好地体现缓冲区的存在。 #include<stdio.h> #include<unistd.h> in…

Java中如何去自定义一个类加载器

之前写过一篇&#xff0c;关于 类加载器和双亲委派的文章&#xff0c;里边提到过可以根据自己的需要&#xff0c;去写一个自定义的类加载器&#xff0c;正好有人问这个问题&#xff0c;今天有时间就来手写一个自定义的类加载器&#xff0c;并使用这个自定义的类加载器来加载一个…

X86 RouterOS 7.18 设置笔记六:端口映射(IPv4、IPv6)及回流问题

X86 j4125 4网口小主机折腾笔记五&#xff1a;PVE安装ROS RouterOS X86 RouterOS 7.18 设置笔记一&#xff1a;基础设置 X86 RouterOS 7.18 设置笔记二&#xff1a;网络基础设置(IPV4) X86 RouterOS 7.18 设置笔记三&#xff1a;防火墙设置(IPV4) X86 RouterOS 7.18 设置笔记四…

代码随想录|二叉树|21合并二叉树

leetcode:617. 合并二叉树 - 力扣&#xff08;LeetCode&#xff09; 题目 给定两个二叉树&#xff0c;想象当你将它们中的一个覆盖到另一个上时&#xff0c;两个二叉树的一些节点便会重叠。 你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠&#xff0c;那么…

LDR6500在Type-C转DP视频双向互传方案

LDR6500在Type-C转DP视频双向互传方案中扮演着核心角色&#xff0c;以下是对该方案的详细解析&#xff1a; 一、LDR6500芯片概述 LDR6500是乐得瑞科技针对USB Type-C标准中的Bridge设备而开发的USB-C DRP&#xff08;Dual Role Port&#xff0c;双角色端口&#xff09;接口USB…

CRM企业客户关系管理系统产品原型方案

客户关系管理系统&#xff08;CRM&#xff09;是企业产品应用中的典范&#xff0c;旨在通过信息技术和互联网技术提升企业核心竞争力&#xff0c;优化企业与顾客在销售、营销和服务方面的互动。本作品提供了一套通用型的CRM系统原型模板&#xff0c;涵盖数据管理、审批流程、统…

RabbitMQ消息持久化与Lazy模式对比分析

RabbitMQ消息持久化与Lazy模式对比分析 在RabbitMQ中&#xff0c;消息持久化与Lazy模式是两种不同的机制&#xff0c;分别针对消息可靠性、存储优化等不同维度设计。以下从六个层面进行深度对比&#xff1a; 一、核心目标与作用对象差异 维度消息持久化&#xff08;delivery_…

linux 命令 tail

tail 是 Linux 中用于查看文件末尾内容的命令&#xff0c;常用于日志监控和大文件快速浏览。以下是其核心用法及常见选项&#xff1a; 基本语法 tail [选项] 文件名 常用选项 显示末尾行数 -n <行数> 或 --lines<行数> 指定显示文件的最后若干行&#xff08;…

某乎x-zse-96加密算法分析与还原

文章目录 1. 写在前面2. 接口分析3. 加密分析4. 算法实现 【&#x1f3e0;作者主页】&#xff1a;吴秋霖 【&#x1f4bc;作者介绍】&#xff1a;擅长爬虫与JS加密逆向分析&#xff01;Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致…

ubuntu 24 安装 python3.x 教程

目录 注意事项 一、安装不同 Python 版本 1. 安装依赖 2. 下载 Python 源码 3. 解压并编译安装 二、管理多个 Python 版本 1. 查看已安装的 Python 版本 2. 配置环境变量 3. 使用 update-alternatives​ 管理 Python 版本 三、使用虚拟环境为项目指定特定 Python 版本…

怎样使用Modbus转Profinet网关连接USB转485模拟从站配置案例

怎样使用Modbus转Profinet网关连接USB转485模拟从站配置案例 Modbus转profinet网关可以将Modbus协议转化为profinet协议&#xff0c;以实现设备之间的数据交互。在实际使用过程中&#xff0c;我们需要使用Modbus协议进行设备通讯&#xff0c;而profinet协议则是用于工业自动化…

一文解读python高阶功能:匿名函数到魔法方法(__call__)

文章目录 一、python中匿名方法的使用使用示例注意事项总结 二、匿名函数和魔法方法的结合示例&#xff1a;结合 lambda 和 __call__解释更复杂的示例 总结 一、python中匿名方法的使用 在 Python 中&#xff0c;匿名方法是通过 lambda 关键字定义的&#xff0c;通常称为 lamb…

云服务器新手配置内网穿透服务(frp)

首先你得有一个公网服务器&#xff0c;有了它你就可以借助它&#xff0c;将自己电脑进行配置内网穿透&#xff0c;让自己内网电脑也可以异地轻松访问。网上教程较多&#xff0c;特此记录我自己的配置&#xff0c;避免迷路&#xff0c;我这里只记录我自己云服务小白&#xff0c;…

基于STM32的火灾报警设备(阿里云平台)

目录 前言&#xff1a; 一、项目介绍和演示视频 二、硬件需求准备 三、硬件框图 1. 原理图 2. PCB 四、CubeMX配置 五、代码框架 前言&#xff1a; 源代码下载链接&#xff1a; https://download.csdn.net/download/m0_74712453/90474701 需要实物的可以私信博主或者…

学习笔记之车票搜索为什么用Redis而不是ES?

在文章正式开始前&#xff0c;大家打开 12306.cn 搜索一趟列车&#xff0c;根据搜索条件判断&#xff0c;数据搜索技术使用 ElasticSearch 或者其它搜索技术是否合适&#xff1f; 这里我先把答案说下&#xff0c;12306 车票搜索用的是 Redis &#xff0c;而不是大家常用的 Ela…