网站打不开 域名做解析,wordpress博客无法重定向,设计公司名称,长沙从寒网络科技有限公司目录 拷贝构造函数一、为什么用拷贝构造二、拷贝构造函数1、概念2、特征1. 拷贝构造函数是构造函数的一个重载形式。2. 拷贝构造函数的参数3. 若未显式定义#xff0c;编译器会生成默认的拷贝构造函数。4. 拷贝构造函数典型调用场景 拷贝构造函数
一、为什么用拷贝构造
日期… 目录 拷贝构造函数一、为什么用拷贝构造二、拷贝构造函数1、概念2、特征1. 拷贝构造函数是构造函数的一个重载形式。2. 拷贝构造函数的参数3. 若未显式定义编译器会生成默认的拷贝构造函数。4. 拷贝构造函数典型调用场景 拷贝构造函数
一、为什么用拷贝构造
日期类传值这里是浅拷贝
#includeiostream
using namespace std;
class Date {
public:Date(int year1, int month1, int day1) {_year year;_month month;_day day;}void Print() {cout _year / _month / _day endl;}
private:int _year ;int _month ;int _day ;
};
int main() {Date d1;d1.Print();return 0;
}运行后
这里进行了传值的拷贝形参传给实参进行了值拷贝也就是浅拷贝所以并没有出现问题。
但是栈类的结构浅拷贝会出现问题
#includeiostream
using namespace std;class Stack{public:Stack(size_t capacity 3){cout Stack(size_t capacity 3) endl;_a (int*)malloc(sizeof(int) * capacity);if (nullptr _a){perror(malloc申请空间失败!!!);}_capacity capacity;_top 0;}~Stack(){cout ~Stack() endl;free(_a);_capacity _top 0;_a nullptr;}private:int* _a;int _capacity;int _top;};
int main() {Stack st1;Stack st2(st1);return 0;
}运行后会变成 从上面我们可以看出程序崩溃了这是为什么呢 原因在于我们的栈的结构体类型中有一个指针来指向下一个结构体当我们进行浅拷贝的时候会将这个地址也拷贝过去但是我们的c会自动调用析构函数那么析构函数就被调用了两次从上面的图中我们也可以看出来析构函数被调用了两次所以程序崩溃了。
那么如何解决这个问题呢我们的C祖师爷就定义了一个拷贝构造函数 来解决这个问题。
二、拷贝构造函数
1、概念 拷贝构造函数只有单个形参该形参是对本类类型对象的引用(一般常用const修饰)在用已存在的类类型对象创建新对象时由编译器自动调用。 2、特征
拷贝构造函数也是特殊的成员函数其特征如下
1. 拷贝构造函数是构造函数的一个重载形式。
2. 拷贝构造函数的参数
拷贝构造函数的参数只有一个且必须是类类型对象的引用使用传值方式编译器直接报错因为会引发无穷递归调用。
下面写一个拷贝构造函数重新进行运行
#includeiostream
using namespace std;class Stack{public:Stack(size_t capacity 3){cout Stack(size_t capacity 3) endl;_a (int*)malloc(sizeof(int) * capacity);//要重新开辟空间if (nullptr _a){perror(malloc申请空间失败!!!);}_capacity capacity;_top 0;}//拷贝构造函数Stack(const Stack stt ) {_a (int*)malloc(sizeof(int) * stt._capacity);if (_a nullptr) {perror(malloc);exit(-1);}memcpy(_a, stt._a, sizeof(int) * stt._top);_capacity stt._capacity;_top stt._top;}~Stack(){cout ~Stack() endl;free(_a);_capacity _top 0;_a nullptr;}private:int* _a;int _capacity;int _top;};
void Func(Stack stt) {//....
}
int main() {Stack st1;Func(st1);return 0;
}就会发现是正常运行如下 //拷贝构造函数Stack(const Stack stt ) {_a (int*)malloc(sizeof(int) * stt._capacity);if (_a nullptr) {perror(malloc);exit(-1);}memcpy(_a, stt._a, sizeof(int) * stt._top);_capacity stt._capacity;_top stt._top;}通过拷贝构造函数我们可以看出是重新开辟了一块空间进行拷贝构造而且我们使用了引用。那么为什么要用引用呢 下面我们用日期类函数进行演示
#includeiostream
using namespace std;
class Date {
public:Date(int year1, int month1, int day1) {_year year;_month month;_day day;}//错误的拷贝构造函数Date(Date d) {_year d._year;_month d._month;_day d._day;}void Print() {cout _year / _month / _day endl;}
private:int _year ;int _month ;int _day ;
};
int main() {Date d1;d1.Print();Date d2(d1);d2.Print();return 0;
}我们会发现代码没有办法运行进行下面的报错 这是由于当我们d2要对d1进行拷贝构造时发生了以下过程 规定传值传参都要去调用拷贝构造函数那么中间就还有临时变量要创建和拷贝这样一环套一环没有终点。如下 综上所以我们要用引用直接将d1赋值给d如下所示
#includeiostream
using namespace std;
class Date {
public:Date(int year1, int month1, int day1) {_year year;_month month;_day day;}//正确的拷贝构造函数Date(Date d) {_year d._year;_month d._month;_day d._day;}void Print() {cout _year / _month / _day endl;}
private:int _year ;int _month ;int _day ;
};
int main() {Date d1;d1.Print();Date d2(d1);d2.Print();return 0;
}3. 若未显式定义编译器会生成默认的拷贝构造函数。
默认的拷贝构造函数对象按内存存储按字节序完成拷贝这种拷贝叫做浅拷贝或者值拷贝。 注意类中如果没有涉及资源申请时拷贝构造函数是否写都可以一旦涉及到资源申请时则拷贝构造函数是一定要写的否则就是浅拷贝。
所以其实日期类是不用进行我们自己写拷贝构造函数的因为日期类浅拷贝就够用了我在上面用日期类进行举例是为了方便我们理解。拷贝构造还是主要用在我开始写的栈类型的程序上。
#includeiostream
using namespace std;class Stack{public:Stack(size_t capacity 3){cout Stack(size_t capacity 3) endl;_a (int*)malloc(sizeof(int) * capacity);//要重新开辟空间if (nullptr _a){perror(malloc申请空间失败!!!);}_capacity capacity;_top 0;}//拷贝构造函数Stack(const Stack stt ) {_a (int*)malloc(sizeof(int) * stt._capacity);if (_a nullptr) {perror(malloc);exit(-1);}memcpy(_a, stt._a, sizeof(int) * stt._top);_capacity stt._capacity;_top stt._top;}~Stack(){cout ~Stack() endl;free(_a);_capacity _top 0;_a nullptr;}private:int* _a;int _capacity;int _top;};
void Func(Stack stt) {//....
}
int main() {Stack st1;Func(st1);Stack st2(st1);return 0;
}通过调试上述代码我们发现它们_a的地址不同但是_capacity、_top的值是相同的成功完成了拷贝构造。 运行后的结果如下
4. 拷贝构造函数典型调用场景
使用已存在对象创建新对象 函数参数类型为类类型对象 函数返回值类型为类类型对象