怎么建设一个简单的网站,武夷山网站推广,申请域名后如何发布网站,四川住房城乡建设厅官网标题#xff1a;【Cpp】类和对象#拷贝构造 赋值重载
水墨不写bug 目录
#xff08;一#xff09;拷贝构造
#xff08;二#xff09;赋值重载
#xff08;三#xff09;浅拷贝与深拷贝 正文开始#xff1a;
#xff08;一#xff09;拷贝构造 拷贝构造函数…标题【Cpp】类和对象#拷贝构造 赋值重载
水墨不写bug 目录
一拷贝构造
二赋值重载
三浅拷贝与深拷贝 正文开始
一拷贝构造 拷贝构造函数只有单个形参该形参是对本类类型对象的引用(一般常用const修饰防止在拷贝的时候 被拷贝的对象 被修改)在用已存在的 类型对象 创建新对象时由编译器自动调用。 1. 拷贝构造函数是构造函数的一个重载形式。 2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用使用传值方式编译器直接报错因为会引发无穷递归调用。 #includestring
using namespace std;
class Person
{
public:Person(char* name, int age 0){_name (char*)malloc(strlen(name)1);_name name;_age age;}Person(Person p)//拷贝构造必须是类对象的引用否则会引发无穷递归{_name (char*)malloc(strlen(p._name) 1);_name p._name;_age p._age;}
private:char* _name;int _age;
};
int main()
{Person p1((char*)zhangsan,35);Person p2(p1);return 0;
}3. 若未显式定义编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝这种拷贝叫做浅拷贝或者值拷贝。 注意在编译器生成的默认拷贝构造函数中内置类型是按照字节方式直接拷贝的而自定义类型是调用其拷贝构造函数完成拷贝的。 4. 编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了还需要自己显式实现吗 对于编译器自己生成的拷贝构造是浅拷贝只能完成对内置类型的拷贝因为内置类型的本质就是一个值或者说就是几个直接携带信息的数据。 但是对于自定义类型其本身指向的地址才是有效的数据它间接指向有效的数据对它本身进行浅拷贝没有实际意义。 由于编译器自动生成的拷贝构造会只完成浅拷贝所以这时候就需要自己手动显示实现自定义类型的深拷贝。 5. 拷贝构造函数典型调用场景 使用已存在对象创建新对象 函数参数类型为类 类型对象也就是普遍的以类对象传参的情况 函数返回值类型为类类型对象 实例 class Person
{
public:Person(char* name, int age 0){_name (char*)malloc(strlen(name)1);_name name;_age age;}Person(Person p)//函数参数类型为类 类型对象也就是普遍的以类对象传参的情况{_name (char*)malloc(strlen(p._name) 1);_name p._name;_age p._age;}Person Modefy()//修改人的信息返回Person这个修改后的类对象{}private:char* _name;int _age;
};
int main()
{Person p1((char*)zhangsan,35);Person p2(p1);//使用已存在对象创建新对象return 0;
}为了提高程序效率一般对象传参时尽量使用引用类型返回时根据实际场景能用引用尽量使用引用。 注意类中如果没有涉及资源申请时拷贝构造函数是否写都可以一旦涉及到资源申请时则拷贝构造函数是一定要写的否则就是浅拷贝。 二赋值重载 C为了增强代码的可读性引入了运算符重载运算符重载是具有特殊函数名的函数也具有其返回值类型函数名字以及参数列表其返回值类型与参数列表与普通的函数类似。 函数名字为关键字 operator后面接需要重载的运算符符号 函数原型返回值类型 operator操作符(参数列表) 实例 Date operator(Date d1)
{//...
} 注意 不能通过连接其他符号来创建新的操作符比如operator (不能创造操作符) 重载操作符必须有一个类类型参数 对于内置类型的操作符重载没有意义因此只能对自定义类型的操作符重载 用于内置类型的运算符其含义不能改变例如内置的整型不 能改变其含义 作为类成员函数重载时其形参看起来比操作数数目少1因为成员函数的第一个参数为隐藏的this . 浮点/ *解引用/ ::域作用限定符/ sizeof计算类型大小操作符 / ?:三目操作符 注意以上5个运算符不能重载。 1. 赋值运算符重载格式 参数类型const T传递引用可以提高传参效率同时防止对象被修改 返回值类型T返回引用可以提高返回的效率有返回值目的是为了支持连续赋值 检测是否自己给自己赋值 返回*this 要复合连续赋值的含义 2. 赋值运算符只能重载成类的成员函数不能重载成全局函数 原因赋值运算符如果不显式实现编译器会生成一个默认的。此时用户再在类外自己实现一个全局的赋值运算符重载就和编译器在类中生成的默认赋值运算符重载冲突了故赋值运算符重载只能是类的成员函数。 3. 用户没有显式实现时编译器会生成一个默认赋值运算符重载以值的方式逐字节拷贝。 注意内置类型成员变量是直接赋值的而自定义类型成员变量需要调用对应类的赋值运算符重载完成赋值。 4.既然编译器生成的默认赋值运算符重载函数已经可以完成字节序的值拷贝了还需要自己实现吗 类似的内置类型自己本身就直接携带信息可以直接拷贝但是自定义类型的直接浅拷贝是没有意义的所以对于自定义类型我们需要自己手动显示实现赋值重载内置类型则不需要。 注意如果类中未涉及到资源管理赋值运算符是否实现都可以一旦涉及到资源管理则必须要实现。
三浅拷贝与深拷贝 浅拷贝和深拷贝是两种不同的拷贝方式用于在编程中复制数据。 浅拷贝是创建一个新的对象新对象的内容与原对象相同但是新对象中的引用类型的成员仍然指向原对象中的引用类型对象。换句话说浅拷贝只是复制了对象的引用而已。当原对象中的引用类型成员发生变化时新对象中的引用类型成员也会随之变化。 深拷贝是创建一个全新的对象将原对象的所有成员包括值类型和引用类型逐一复制到新对象中。换句话说深拷贝会复制对象中的引用类型并创建一个新的引用类型对象。当原对象中的引用类型成员发生变化时新对象中的引用类型成员不会随之变化。 浅拷贝和深拷贝的区别在于对于引用类型成员的处理方式。浅拷贝只复制引用而深拷贝会创建新的引用类型对象。 举一个例子 创建一个栈的对象stack_1; 拷贝构造一个stack_2 如果使用的是编译器默认生成的浅拷贝方式那么对 stack_2的操作本质上也就是对stack_1的操作因为栈的底层是一个动态开辟的堆区数组创建stack_2时因为浅拷贝只是拷贝了栈区上stack_1的指向堆的一个指针。因而两个栈指向的同一块堆上的数组。 深拷贝则是在堆上重新开辟了一个数组并把stack_1的值赋给stack_2。 完~
未经作者同意禁止转载