深圳网站建设龙华新科,网站被惩罚之后怎么做,做SEO用dede还是wordpress,国外域名。国内网站目录
拷贝构造函数
特性
自定义类型的传值传参和传引用传参对比
赋值运算符重载 拷贝构造函数
基本概念#xff1a;只有单个形参#xff0c;该形参是对本类类型对象的引用#xff08;一般常用const修饰#xff09;#xff0c;在创建一个已存在对象一模一样的新对象时…目录
拷贝构造函数
特性
自定义类型的传值传参和传引用传参对比
赋值运算符重载 拷贝构造函数
基本概念只有单个形参该形参是对本类类型对象的引用一般常用const修饰在创建一个已存在对象一模一样的新对象时由编译器自动调用
调用格式类名 新对象同类对象名
类中格式 类名const 类名 变量名
作用创建一个已存在对象一模一样的新对象
特性
1、拷贝构造函数是构造函数的一个重载形式重名构成函数重载
2、拷贝构造函数的传递的参数只有一个且类型必须是对象的引用使用传值传参的方式会引发无穷递归调用编译器报错
#include iostream
using namespace std;class Date
{
public:Date(int year 1900, int month 1, int day 1){_year year;_month month;_day day;}//正确写法Date(Date d)//最佳写法Date(const Date d)Date(Date d)//错误写法{_year d._year;_month d._month;_day d._day;}
private:int _year;int _month;int _day;
};int main()
{Date d1(2024,3,7);Date d2(d1);return 0;
} 自定义类型的传值传参和传引用传参对比
#include iostream
using namespace std;class Date
{
public:Date(int year 1900, int month 1, int day 1){_year year;_month month;_day day;}Date(Date d){_year d._year;_month d._month;_day d._day;}
private:int _year;int _month;int _day;
};//传值传参
void func1(Date d)//d是d1的拷贝
{}//传引用传参
void func2(Date rd)//rd是d1的别名
{}int main()
{Date d1(2024,3,7);func1(d1);func2(d1);return 0;
}
调试过程20240307_111203-CSDN直播 在调用func1函数前传参的过程中d1对象的成员变量的数值会传递给d会先进入拷贝构造函数中执行完拷贝构造后才会调用func1函数 在调用func2函数前传参的过程中不会进入拷贝构造函数在传参结束后会直接调用func2函数 这是因为C规定将一个对象作为参数传递给函数时如果参数是按值传递而不是引用会调用拷贝构造函数如果我们不额外的写这两个函数来找寻找传值调用和传参调用的区别而是直接将拷贝构造函数写成DateDate A
就会造成无限递归由于我们想要用d1对象中的成员变量的值去初始化d2对象的成员变量的值在传值传参时d1传递给拷贝构造函数的是一个它值所有成员变量的值的临时拷贝这个值也可以被视为一个新的对象e1想要做的是初始化这个新的对象然后将初始化的结果带回去带不带的回去还是一说传值调用形参是实参的拷贝对形参的改变不会影响实参当我们尝试初始化这个对象时又会调用拷贝构造函数此时又会生成e1的拷贝新对象f1...... 结论直接记住拷贝构造函数的格式即可当你尝试使用传值传参时编译器会报错 调用函数时先传参后调用 #include stdio.h
int func(int a)
{return a;
}int main()
{func(5);return 0;
} 3、拷贝构造函数记得引用前要加constconst可以很好的保护被引用的对象d1对象的值不能被d2对象的值初始化 否则出现原本是想借用拷贝构造函数初始化新对象的成员变量但是赋值两端的内容写反了新对象的成员变量随机值反而把拷贝构造函数的成员变量初始化成随机值了 d2(d1)看起来只是将对象d1作为实参传递了但实际上还有一个包含d2对象地址的this指针 4、若为显示定义拷贝构造函数编译器会生成默认的拷贝构造函数默认拷贝构造函数会对内置类型成员变量会进行值拷贝将成员变量的字节依照原有的顺序一个一个的拷贝也叫浅拷贝
#include iostream
using namespace std;class Date
{
public:Date(int year 1900, int month 1, int day 1){_year year;_month month;_day day;}void Print(){cout _year - _month - _day endl;}//没有显式定义拷贝构造函数
private:int _year;int _month;int _day;
};int main()
{Date d1(2024,3,7);Date d2(d1);d1.Print();d2.Print();return 0;
} 5、 拷贝构造函数也是构造函数
#include iostream
using namespace std;class Time
{
public:~Time(){cout ~Time() endl;}//强制编译器生成默认构造函数 Time() default;Time(const Time t){cout Time(const Time t) endl;_hour t._hour;_minute t._minute;_mecond t._mecond;}
private:int _hour;int _minute;int _mecond;
};class Date
{
public:Date(int year 1900, int month 1, int day 1){_year year;_month month;_day day;}void Print(){cout _year - _month - _day endl;}
private://内置类型int _year;int _month;int _day;//自定义类型Time _t;
};int main()
{Date d1(2024,3,7);Date d2(d1);d1.Print();d2.Print();return 0;
} 由于我们在Time类中提供了拷贝构造函数所以编译器不会生成默认构造函数对此我们可以使用default关键字强制编译器生成默认构造函数
6、类中没有涉及资源申请时拷贝构造函数是否写都可以一旦涉及资源申请则拷贝构造函数一定要写否则就是浅拷贝
#include iostream
using namespace std;
typedef int DataType;
class Stack
{
public://默认构造函数Stack(size_t capacity 10){_array (DataType*)malloc(capacity * sizeof(DataType));if (nullptr _array){perror(malloc申请空间失败);return;}_size 0;_capacity capacity;}//插入函数void Push(const DataType data){// CheckCapacity();_array[_size] data;_size;}//使用默认拷贝构造函数//析构函数~Stack(){if (_array){free(_array);_array nullptr;_capacity 0;_size 0;}}
private:DataType* _array;size_t _size;size_t _capacity;
};int main()
{Stack s1;s1.Push(1);s1.Push(2);s1.Push(3);s1.Push(4);Stack s2(s1);return 0;
} 这是因为实例化s1对象时在堆上开辟了个空间用于存放元素接着s2对象要用s1对象的成员变量进行初始化Stakc类没有显示定义拷贝构造函数编译器会生成一份默认的拷贝构造函数默认拷贝构造函数是按值拷贝的即将s1中的内容原封不动的拷贝到s2中对于_size和_capacity没问题但是_array存放的可是s1在堆上开辟的空间的地址此时将该地址的值也原封不动的传递给了s2的_array此时s1和s2对象的_array指向同一片空间当main函数结束时s2先销毁s2销毁时调用析构函数释放掉申请的空间由于s1不知道所以会将该空间再次释放同一块内存空间的多次释放肯定会造成程序崩溃 因此对于申请了空间资源的类我们要进行深拷贝
#include iostream
using namespace std;
typedef int DataType;
class Stack
{
public://默认构造函数Stack(size_t capacity 10){_array (DataType*)malloc(capacity * sizeof(DataType));if (nullptr _array){perror(malloc申请空间失败);return;}_size 0;_capacity capacity;}//插入函数void Push(const DataType data){// CheckCapacity();_array[_size] data;_size;}//深拷贝Stack(const Stack s){DataType* tmp (DataType*)malloc(s._capacity * (sizeof(DataType)));if(tmp nullptr){perror(malloc fail);exit(-1);}memcpy(tmp, s._array, sizeof(DataType) * s._size);_array tmp;_size s._size;_capacity s._capacity;}//析构函数~Stack(){if (_array){free(_array);_array nullptr;_capacity 0;_size 0;}}
private:DataType* _array;size_t _size;size_t _capacity;
};int main()
{Stack s1;Stack s2(s1);return 0;
} ~over~