C++类的六个默认成员函数(详细解析与总结)

目录

前言:

一、构造函数

a.特点

b.注意事项

1.首先明确什么是默认构造函数

2.默认构造函数对内置类型与自定义类型的处理

c.总结

二、析构函数

a.特点

b.注意事项

1.什么时候写析构函数?

2.析构函数对内置类型与自定义类型的处理

c.总结

三、拷贝构造

a.特点

b.特点的逐个分析以及注意事项

1.为什么拷贝构造要使用传引用返回?

2.为什么使用const修饰类类型对象的引用?

3.系统提供构造与拷贝构造的规则

4.拷贝构造对内置类型与自定义类型的处理

5.如果需要析构函数,则一般都需要拷贝构造与赋值重载

c.总结

四、运算符重载 

a.特点

b.实现日期类的比较

c.函数重载与运算符重载

d.总结

五、赋值重载

a.日期类实现赋值重载

b.赋值重载与拷贝构造

c.赋值重载对类型的处理

d.再来看流插入

e.日期类打印自定义类型

f.补充内联函数

g.总结

六、const修饰的非静态成员函数

七、const修饰的取地址操作符重载

总结:

本篇内容对六个默认成员函数进行了一个较为详细的分析,需要反复的复习并配合使用,其中构造,拷贝构造与运算符重载比较重要,在后面用的很多,后面还会有文章对这部分进行补充,例如友元函数和一些关键字。


 

前言:

本篇介绍的是有关于c++类中的六个默认成员函数(文章中附上了总结性的思维导图),为什么说是默认成员函数呢?因为大多数情况下,再一个类里面,如果没有写,编译器将会自动生成;如果写了某个,编译器将不会生成对应的默认成员函数;其次对于空类,六个默认成员函数不会生成,只会生成1byte的占位符。 


 

一、构造函数

a.特点

注意:
1.不用写返回值不代表返回值是void。

2.构造函数可重载说明一个类可以有多个构造函数。

3.第三条说明栈里面对象实例化需要初始化,可以在类里面用构造函数来初始化,再实例化对象就会自动调用初始化的构造函数了;无参的构造函数直接对对象实例化就自动调用;有参的构造函数在对象实例化时传参即可调用。

b.注意事项
1.首先明确什么是默认构造函数
class Date
{
public:private:int _year = 1;int _month = 1;int _day = 1;
};int main()
{Date d1;return 0;
}

上面的代码是没自己写构造函数,所以可以直接调用编译器默认生成的,在对象实例化的时候自动初始化,注意自动生成的是无参的构造。

class Date
{
public://是默认构造Date()//无参的构造{_year = 1;_month = 1;_day = 1;}Date(int year, int month, int day)//带参的构造{_year = year;_month = month;_day = day;}private:int _year = 1;int _month = 1;int _day = 1;
};int main()
{//无参的构造调用不能这样写,编译器无法分明是函数声明还是构造函数Date();//去调用无参的默认构造Date d1;//带参函数构造调用Date d2(2024, 3, 27);return 0;
}

第一个构造为无参的构造,我们将它看为默认构造函数;第二个构造函数为带参的构造,不是默认的构造函数,需要显示的调用。

它们构成函数重载,需要注意的是,调用无参的构造不能直接写成Date(),这样编译器识别不出这是函数声明还是构造函数的调用。

class Date
{
public://是默认构造Date()//无参的构造{_year = 1;_month = 1;_day = 1;}Date(int year, int month, int day)//带参的构造{_year = year;_month = month;_day = day;}//是默认构造Date(int year = 1, int month = 1, int day = 1)//将上方二者合而为一的全缺省的构造{_year = year;_month = month;_day = day;}private:int _year = 1;int _month = 1;int _day = 1;
};int main()
{//无参的构造调用不能这样写,编译器无法分明是函数声明还是构造函数Date();//去调用默认构造Date d1;//带参函数构造调用Date d2(2024, 3, 27);return 0;
}

上面的第三个构造函数为全缺省的构造函数,将无参的与带参的构造函数结合到了一起,我们也认为它为默认构造函数。

但是需要考虑的是,全缺省的能和无参的一起使用吗???

答案是不能的,如果同时存在,那调用无参的构造函数应该去调用哪一个呢?会产生歧义,编译器会报对重载函数的调用不明确的错误;同样的,代码中第二个构造与第三个构造也不能同时存在,如果同时存在,那调用带参的构造函数时应该去调用谁呢?编译器会报构造函数已定义的错误。

2.默认构造函数对内置类型与自定义类型的处理

在我们调用默认生成的构造函数的时候,会发现,为什么用默认的构造函数初始化,对象中的成员变量为随机值,这有什么mao用???

这就关于我们默认成员函数的另一性质了,对于默认构造函数来说:

内置类型成员不做处理,自定义类型成员取调用它的默认构造(不用传参的构造)。

c++把类型分为内置类型(基本类型)与自定义类型:

内置类型:语言提供的类型,如int,char,double...以及这些类型的任意指针。

自定义类型:class,struct,union等自己定义的类型

后来c++11为了处理内置类型的初始化,增加了一条:

内置类型的声明位置可以给缺省值,注意不是初始化(因为给缺省值没有开空间),所以再对内置类型初始化时就不用给缺省值了(有些编译器会直接初始化为0,但是不要依赖)。 

c.总结

二、析构函数

a.特点

在对象销毁时会自动调用析构函数,完成对象中资源的清理工作。

b.注意事项
1.什么时候写析构函数?

析构函数什么时候写呢?像我们后面要完成的日期类可以不写析构函数,因为对象为局部变量,出了作用域就销毁了;而对于像栈的实现,有动态开辟的空间,在堆区上开辟空间,要写析构函数清理资源,否则会造成内存泄露,后面会举例说明。

2.析构函数对内置类型与自定义类型的处理

与构造函数一样,内置类型不做处理,自定义类型会调用它的析构函数。 

c.总结

三、拷贝构造

拷贝构造涉及内容比较深入,且注意点也很多,需要细细分析。

a.特点

b.特点的逐个分析以及注意事项
class Date
{
public:/*Date(){_year = 1;_month = 1;_day = 1;}Date(int year, int month, int day){_year = year;_month = month;_day = day;}*/Date(int year = 12, 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;}private:int _year = 1;int _month = 1;int _day = 1;
};int main()
{//调用默认(全缺省)构造函数并使用函数中的缺省值Date d1;//调用默认(全缺省)构造函数并传参Date d2(2024, 3, 27);//调用拷贝构造Date d3(d2);//Date d3=d2;return 0;
}
1.为什么拷贝构造要使用传引用返回?

结合我们前面的知识,赋值其实就是拷贝(联想c++基础语法篇的隐式类型转换),对于类的对象来说,传值其实就是要去调用它的拷贝构造初始化,但是我们进行拷贝构造需要先传参,传参又是传值传参,传值传参又要调用拷贝构造......就陷入了死递归,且编译器会立刻报错。再根据我们之前c++语法讲解的使用传引用返回可以减少拷贝,所以我们在这里使用一个传引用返回就解决了这里的问题。(c++基础语法篇链接:http://t.csdnimg.cn/hCM1P)到这里有没有体会到知识融汇贯通的感觉呢?

2.为什么使用const修饰类类型对象的引用?

根据上面的代码,假设d2为const对象修饰的,我们在传参的时候传给类类型的引用d,此时d不是一个const修饰的引用,所以可以对其进行修改,这样我们就将权限放大了,而在任何时候权限只能缩小不能放大。

3.系统提供构造与拷贝构造的规则

搜先,由于拷贝构造是构造函数的重载,其实也就是构造的一种,所以我们如果自己写了拷贝构造,编译器就不会给我们提供任何默认的构造函数了,所以再想使用编译器生成的默认的无参构造函数初始化,就不行了,需要我们自己提供构造函数:

其次,如果我们提供了普通的有参的构造函数,且不是拷贝构造,那编译器将不再提供无参的默认构造,但是会提供拷贝构造(是浅拷贝),如下没有手写拷贝构造d3也能完成拷贝:

4.拷贝构造对内置类型与自定义类型的处理

对于拷贝构造而言,自定义类型的拷贝,需要调用拷贝构造;

内置类型可以直接拷贝,就像我们将d2拷贝给d3;或者需要深拷贝(默认生成的或者我们直接赋值的是浅拷贝,深拷贝需要我们自己写),因为拷贝是按字节去拷贝的,对于像动态开辟的变量,只是按字节拷贝,拷贝出来这两个动态变量在堆区上指向的位置却还是一样的,就像我们将栈的实现封装为stack这样的一个类,内置类型使用了动态开辟的变量,再进行拷贝,这样就会引发问题:

可以看到,拷贝出来的两个对象中的_a都指向了同一块空间(因为你只是负责拷贝字节,没法改变空间的指向啊),这样就会引发析构时需要析构两次,并且在这个场景下参与拷贝的两个对象插入删除数据会互相影响。

深拷贝:

再给st2开辟一块空间,再让st1按字节拷贝过去

以上是针对内置类型的深浅拷贝,下面是对于自定义类型的默认拷贝构造:

对于MYQueue这样的自定义类型,编译器默认生成的这三个构造函数的都可以用。

_size是内置类型,是值拷贝。

成员变量中的_pushST与_popST都是自定义类型(这里的stack没有封装成一个类,跟上面的stack不一样,这里是stack是自定义类型,会调用拷贝构造,但是这个自定义类型中有动态开辟的变量,所以要考虑深拷贝;而上面的stack是一个类,_a是它的成员,是一个内置类型,默认是浅拷贝(值拷贝),所以也需要考虑深拷贝。二者有些区别,注意区分),如果使用编译器默认生成的就是浅拷贝,因为它们都含有动态开辟的变量:

5.如果需要析构函数,则一般都需要拷贝构造与赋值重载

有了上面的知识,我们再来理解这句话就更加明白了,因为如果需要我们手写析构函数,一般来说是默认的析构函数不够用了,例如动态开辟的变量,所以为了防止刚刚提到的浅拷贝导致的双重释放,我们就要自己来写一个拷贝构造与赋值重载来防止浅拷贝。

c.总结

四、运算符重载 

下面要谈到赋值重载,就要先了解运算符重载。

a.特点

b.实现日期类的比较
class Date
{
public:/*Date(){_year = 1;_month = 1;_day = 1;}Date(int year, int month, int day){_year = year;_month = month;_day = day;}*/Date(int year = 12, 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;}//d1==d2bool operator==(const Date& d)//这里使用引用是因为函数传参也需要拷贝,引用来减少拷贝{return  _year == d._year//this->_year==d._year&& _month == d._month&& _day == d._day;}//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);}//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);}private:int _year = 1;int _month = 1;int _day = 1;
};int main()
{Date d1(2023, 3, 28);Date d2(2024, 3, 28);//调用时相当于d1.operator==(d2)//调用也可以写为operator==(d1,d2),但一般不会这样写cout<<(d1 == d2)<<endl;//0cout<<(d1 < d2)<<endl;//1cout<<(d1 > d2)<<endl;//0cout<<(d1 >= d2)<<endl;//0cout<<(d1 <= d2)<<endl;//1cout<<(d1 != d2)<<endl;//1//调用默认(全缺省)构造函数并使用函数中的缺省值//Date d1;//调用默认(全缺省)构造函数并传参//Date d2(2024, 3, 27);//调用拷贝构造//Date d3(d2);return 0;
}

注意使用时:

例如d1==d2,也可以写为operator==(d1,d2)(但是一般不会这样写),在调用的时候会转换为d1.operator==(d2),所以传的this指针也是第一个参数就是d1,第二个参数为d2。

这里比较返回bool值判断真假,在打印时需要注意,<<的优先级高于==等运算符,所以要加上括号。

进行比较的运算符的重载时,可以先写==与<或者其它的,然后其它的可以复用。

c.函数重载与运算符重载

运算符重载实际就是函数重载。

d.总结

五、赋值重载

我们来围绕日期类来进行举例说明,且下面的知识的梳理都是循序渐进的。

a.日期类实现赋值重载
class Date
{
public:/*Date(){_year = 1;_month = 1;_day = 1;}Date(int year, int month, int day){_year = year;_month = month;_day = day;}*/Date(int year = 12, 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;}//d1==d2bool operator==(const Date& d)//这里使用引用是因为函数传参也需要拷贝,引用来减少拷贝{return  _year == d._year//this->_year==d._year&& _month == d._month&& _day == d._day;}//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);}//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);}void Print(){cout << _year << "/" << _month << "/" << _day << endl;}Date& operator=(const Date& d){if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;}private:int _year = 1;int _month = 1;int _day = 1;
};int main()
{Date d1(2023, 3, 28);Date d2(2024, 3, 28);Date d3(2025, 3, 28);//调用时相当于d1.operator==(d2)//调用也可以写为operator==(d1,d2),但一般不会这样写cout<<(d1 == d2)<<endl;//0cout<<(d1 < d2)<<endl;//1cout<<(d1 > d2)<<endl;//0cout<<(d1 >= d2)<<endl;//0cout<<(d1 <= d2)<<endl;//1cout<<(d1 != d2)<<endl;//1d3 = d1 = d2;d1.Print();d3.Print();//调用默认(全缺省)构造函数并使用函数中的缺省值//Date d1;//调用默认(全缺省)构造函数并传参//Date d2(2024, 3, 27);//调用拷贝构造//Date d3(d2);return 0;
}

注意:
 1.为什么要带返回值?

因为对于赋值运算符来说,例如i=j=k这个表达式,j=k这个表达式返回左操作数,返回值    再作为右操作数再赋值给给i。  

所以我们要支持连续赋值,例如d3=d1=d2,d1作为返回值对应*this,所以返回d1,那为什么要用*this呢?因为*this出了赋值重载的作用域还在(因为d1是在主函数定义的,生命周  期在主函数里)所以可以直接返回*this。

 2.为什么参数要用引用?

因为可以减少拷贝。当然这里不加&也不会死循环,因为传值传参调用拷贝构造,我们已经实现过拷贝构造了,调用完拷贝构造就进赋值重载函数了,只有自己对自己传值传参的拷贝构造才会死循环。

 3.为什么函数体要这样写?

函数中要考虑自己对自己赋值,判断一下防止自己对自己赋值。这里调用d1=d2也就是调用d1.operator=(d2)。

b.赋值重载与拷贝构造

注意区分赋值重载与拷贝构造,赋值重载是对于两个实例化的对象而言的。 

c.赋值重载对类型的处理

理解为与拷贝构造一样,也要考虑双重释放的问题。

d.再来看流插入

有了前面的知识储备,我们再来理解一下流插入与流提:

查阅官方文档,我们可以看到流插入也是经过了运算符的重载,而这个类就是我们库中的ostream这个类,运算符重载被封装在这个类里面了;而对于的我们使用cout,cin(cin是istream的对象)就是根据这个类创建的对象,然后去调用对应的运算符重载函数。

再进一步理解为什么我们使用c++中的流插入与流提取可以自动识别类型了,因为是在运算符重载中帮你实现好了:

上面的运算符重载都构成函数重载。假设我们现在有一个int类型的i与double类型的d,去使用流插入就是:

cout<<i;//cout.operator<<(i)   --->int
cout<<d;//cout.operator<<(d)  --->double

e.日期类打印自定义类型

结合前面的知识,我们知道了cout其实就是ostream的对象,现在我们来完成日期类的打印:

上面的可以完成吗?答案是不可以的,因为格式不符合我们的习惯:

调用的时候,由于第一个参数我们需要传递this指针,所以调用的时候写法只能如上图写。

那怎么办呢?我们不定义在类中不就好了:

 但是又发现,类中的保护起来的成员不让访问啊?那我们再让成员放开,有些不值当啊,所以我们可以有两种解决方案:

提供公有的成员函数来获取例如GetYear()等;或者提供一个友元函数(友元函数在类和对象的总结篇会细说):

注意位置放在类中公有和私有域的外面,这样我们的友元函数就能访问类中的成员了,此时调用就变为了:

现在完了吗?还没有!我们还需要考虑连续的调用(流插入从左往右连续调用),所以我们需要返回值,out是cout的别名,返回的其实就是cout:

完整代码:

class Date
{friend ostream& operator << (ostream& out, const Date& d);public:/*Date(){_year = 1;_month = 1;_day = 1;}Date(int year, int month, int day){_year = year;_month = month;_day = day;}*/Date(int year = 12, 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;}//d1==d2bool operator==(const Date& d)//这里使用引用是因为函数传参也需要拷贝,引用来减少拷贝{return  _year == d._year//this->_year==d._year&& _month == d._month&& _day == d._day;}//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);}//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);}void Print(){cout << _year << "/" << _month << "/" << _day << endl;}Date& operator=(const Date& d){if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;}private:int _year = 1;int _month = 1;int _day = 1;
};ostream& operator << (ostream & out, const Date & d)
{out << d._year << "年" << d._month << "月" << d._day << "日" << endl;return out;
}int main()
{Date d1(2023, 3, 28);Date d2(2024, 3, 28);Date d3(2025, 3, 28);//调用时相当于d1.operator==(d2)//调用也可以写为operator==(d1,d2),但一般不会这样写cout<<(d1 == d2)<<endl;//0cout<<(d1 < d2)<<endl;//1cout<<(d1 > d2)<<endl;//0cout<<(d1 >= d2)<<endl;//0cout<<(d1 <= d2)<<endl;//1cout<<(d1 != d2)<<endl;//1d3 = d1 = d2;d1.Print();d3.Print();cout << d3;//调用默认(全缺省)构造函数并使用函数中的缺省值//Date d1;//调用默认(全缺省)构造函数并传参//Date d2(2024, 3, 27);//调用拷贝构造//Date d3(d2);return 0;
}

f.补充内联函数

如果我们在头文件中定义一个函数:

如果没有定义只有声明,那么就需要链接找到定义,call的时候没有地址,就需要到符号表里面去找函数的地址;如果有定义,再编译阶段就能拿到函数的地址,直接call地址就能找到这个函数。

而内联函数不会进符号表

所以我们在将内联函数定义到头文件时,要确保头文件中有定义和声明,这样在编译的阶段就能拿到函数的地址。不然没有定义需要去链接call内联函数的地址,就要去符号表找函数的地址,但是是找不到的。

g.总结

六、const修饰的非静态成员函数

 调用Print这里传递的还有&aa给this指针,而&aa的类型是const A*,传递给Print()后,变成了A* this,权限被放大了,但*this又不能改变,所以如图const写后面表示const修饰*this,this类型变成了const A*,不这样写编译器会报错。类内部不改变成员变量的成员函数,最好加上const(声明定义分离的都要加),const对象和普通对象都能调用。

 

通常间接的调用需要注意要加上const防止权限放大。Print中的this指针是个const A*类型的,用法Func的x去调用要确保x是一个const A类型的,防止权限放大。

 

七、const修饰的取地址操作符重载

一般不需要重载,使用编译器默认生成的即可。

也可写:

需要注意的是,不能加任何参数,不然就是被看做按位与&的重载了。

可以用作于不想让别人取地址,直接返回一个空。

总结:

本篇内容对六个默认成员函数进行了一个较为详细的分析,需要反复的复习并配合使用,其中构造,拷贝构造与运算符重载比较重要,在后面用的很多,后面还会有文章对这部分进行补充,例如友元函数和一些关键字。

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

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

相关文章

pythonselenium自动化测试实战项目

说明&#xff1a;本项目采用流程控制思想&#xff0c;未引用unittest&pytest等单元测试框架 一.项目介绍 目的 测试某官方网站登录功能模块可以正常使用 用例 1.输入格式正确的用户名和正确的密码&#xff0c;验证是否登录成功&#xff1b; 2.输入格式正确的用户名和不…

【面试经典 | 150】单词拆分

文章目录 Tag题目来源解题思路方法一&#xff1a;动态规划 写在最后 Tag 【动态规划】【字符串】 题目来源 139. 单词拆分 解题思路 方法一&#xff1a;动态规划 定义状态 定义 dp[i] 表示字符串 s 前 i 个字符组成的字符串&#xff08;s[0, ..., i-1]&#xff09;是否能被…

【Node.js】模块化

概述 Nodejs 模块化规范遵循两套规范&#xff1a; Common JSES Module Common JS 引入模块&#xff08;require&#xff09;支持四种格式 支持引入内置模块例如 http os fs child_process 等const fs require(fs)&#xff0c;高版本也可以使用const fs require(node:fs…

【Java SE】封装

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 文章目录 1. 封装1.1 封装是什么1.2 封装的意义1.3 访问修饰限定符1.3.1 在Java中如何实现封装1.3.2 各种访问修饰限定…

SpringCloud微服务集成Dubbo

1、Dubbo介绍 Apache Dubbo 是一款易用、高性能的 WEB 和 RPC 框架,同时为构建企业级微服务提供服务发现、流量治理、可观测、认证鉴权等能力、工具与最佳实践。用于解决微服务架构下的服务治理与通信问题,官方提供了 Java、Golang 等多语言 SDK 实现。使用 Dubbo 开发的微服…

【二叉树】Leetcode 230. 二叉搜索树中第K小的元素【中等】

二叉搜索树中第K小的元素 给定一个二叉搜索树的根节点 root &#xff0c;和一个整数 k &#xff0c;请你设计一个算法查找其中第 k 个最小元素&#xff08;从 1 开始计数&#xff09;。 示例1&#xff1a; 输入&#xff1a;root [3,1,4,null,2], k 1 输出&#xff1a;1 解…

在 fstab文件中配置 UUID方式自动挂载数据盘、swap、目录(**)

linux如何挂在硬盘&#xff0c;自动挂载和手动挂载&#xff08;详细说明&#xff09;https://gitcode.csdn.net/65eedcea1a836825ed7a06f4.html 解决linux重启后磁盘挂载失效的问题 https://blog.csdn.net/sugarbliss/article/details/107033034 linux /etc/fstab 文件详细说…

UG NX二次开发(C#)-通过曲线组生成NURBS曲面

文章目录 1、前言2、UG NX中通过曲线组生成NURBS曲面的操作3、采用NXOpen C#方法的源代码1、前言 在UG NX中,曲线、曲面的操作使用比较多,对于创建NURBS曲面,可以通过曲线组来生成,本文以NXOpen C#的方法实现通过曲线组生成NURBS曲面的功能。对于UG NX二次开发感兴趣或者有…

探索多种数据格式:JSON、YAML、XML、CSV等数据格式详解与比较

title: 探索多种数据格式&#xff1a;JSON、YAML、XML、CSV等数据格式详解与比较 date: 2024/3/28 17:34:03 updated: 2024/3/28 17:34:03 tags: 数据格式JSONYAMLXMLCSV数据交换格式比较 1. 数据格式介绍 数据格式是用于组织和存储数据的规范化结构&#xff0c;不同的数据格…

【aws】架构图工具推荐

碎碎念 以前以为日本冰箱论是个梗&#xff0c;结果居然是真的。用光盘传真其实还能理解&#xff08;毕竟我也喜欢电子古董2333&#xff09;&#xff0c;但是画架构图居然用的是excel&#xff0b;截图&#xff01;啊苍天呐&#xff0c;然后看到隔壁工位用excel画web原型又感觉释…

将数字城市复制到虚拟空间,如何搭建实景三维虚拟场景?

什么是实景三维&#xff1f; 实景三维&#xff08;3D Real Scene&#xff09;是一个专业术语&#xff0c;它指的是对一定范围内人类生产、生活和生态空间进行真实、立体、时序化反映和表达的数字虚拟空间。它是新型基础测绘的标准化产品&#xff0c;也是国家重要的新型基础设施…

权限提升-系统权限提升篇数据库提权PostsqlRedis第三方软件提权密码凭据钓鱼文件

知识点 1、数据库到Linux-数据库提权-Redis 3、数据库到Linux-数据库提权-PostgreSQL 4、计算机用户到系统-第三方软件-各类应用 章节点&#xff1a; 1、Web权限提升及转移 2、系统权限提升及转移 3、宿主权限提升及转移 4、域控权限提升及转移 Windows提权&#xff1a; 1、…

Linux 基于HAProxy+KeepAlived实现

Linux 基于HAProxyKeepAlived实现 1. 介绍1.1 高可用&#xff08;HA-High Avaialbility&#xff09;1.2 负载均衡&#xff08;LB-Load Balance&#xff09;1.3 HAProxy1.4 KeepAlived 2. 后端服务为Nginx2.1 系统拓扑2.2 环境说明2.3 前提条件2.4 详细步骤2.4.1 机器初始化2.4.…

Python列表、元组、字典及集合

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、列表定义方式&#xff1a; 二、元组1、定义方式&#xff1a;2、元组中的物理存储地址不可修改,如果修改则会报错&#xff0c;但是元组中的列表、字典项等却可以…

React-1-jsx基础-事件绑定-样式处理

一.JSX基础-概念和本质 1.1 什么是JSX JSX是JavaScript和XML&#xff08;HTML&#xff09;的缩写&#xff0c;表示在JS代码中编写HTML模版结构,它是React中编写UI模版的方式 优势&#xff1a; 1. HTML的声明式模版写法 2. JS的可编程能力 JSX的本质&#xff1a; JSX并不是标…

vivado 手动布线

手动路由 手动路由允许您为网络选择特定的路由资源。这给了你对信号将要采用的路由路径的完全控制。手动路由不调用route_design。路线在路线数据库中直接更新。当您想精确控制网络的延迟时&#xff0c;可能需要使用手动路由。对于例如&#xff0c;假设有一个源同步接口&#…

如何查看JVM使用的是什么垃圾收集器

文章目录 一、背景分析二、查看垃圾收集器三、理解的偏差四、深挖 demo 代码五、总结 一、背景分析 无论讨论对象的内存分配&#xff0c;还是讨论内存的回收策略或是算法&#xff0c;都需要明确指出是基于哪种垃圾收集器进行的讨论。所以&#xff0c;很自然地就想到这个问题&a…

脱敏技术!!!

什么是数据脱敏&#xff1f;&#xff1f;&#xff1f; 数据脱敏&#xff08;Data Masking&#xff09;是一种数据安全技术&#xff0c;旨在通过预先设定的规则和算法&#xff0c;对原始数据中包含的敏感信息进行变形处理&#xff0c;使得这些信息在非生产环境&#xff08;例如…

考研数学|汤家凤1800基础部分要做完吗?

我教你一个方法&#xff0c;保证让你高质量的做完1800基础部分&#xff0c;而且还不用把所有题目都做了 我当然不是教你如何投机取巧&#xff0c;投机取巧是考不了高分的&#xff0c;我教你的都是我在实际考研过程中实际运用到的方法&#xff01; 其实这个方法也是我在二战的时…

C#手术麻醉系统源码 可对接HIS LIS PACS 医疗系统各类设备 医院手麻系统源码

C#手术麻醉系统源码 可对接HIS LIS PACS 医疗系统各类设备 手术麻醉信息管理系统主要还是为了手术室开发提供全面帮助的系统&#xff0c;其主要是由监护设备数据采集子系统和麻醉临床系统两个子部分组成。包括从手术申请到手术分配&#xff0c;再到术前访视、术中记录及术后…