#include <iostream>
using namespace std;
//拷贝构造函数(经常用来对当前变量进行初始化)
/*
作用:
就是用来复制对象的,在使用这个对象的实例来初始化这个对象的一个新的实例需要调用的情况
1) 一个对象作为函数参数,以值传递的方式传入函数体
2) 一个对象作为函数返回值,以值传递的方式从函数返回
3) 一个对象用于给另外一个对象进行初始化(常称为赋值初始化)
Circle(const Circle &c) ;//拷贝构造函数
解释:
1.第一个类名是函数名,需要和类名完全一样
2.一般使用const,也有例外
3.第二个类名是类的名字
4.& 变量名:传引用
*/
/*******************************************/
//浅拷贝:类在构造函数中没有对象成员、没有在堆中申请内存,可以使用浅拷贝
//深拷贝:有对象成员、指针对象成员,构造函数中申请了内存.在拷贝构造函数中实例化对象,就是深拷贝
//在对象成员中有有指针和引用时,这两种拷贝没区别。
/*******************浅拷贝************************/
class FA
{
public:
FA(){}
FA(int x)
{
this->FA_a = x;
cout << "A的构造函数" << " FA_a的值:" << FA_a << endl;
}
int FA_a;
};
FA FA1(2);
FA FA2;
FA2 = FA1;//浅拷贝(内存对齐的赋值)
FA FA3(FA1);//浅拷贝: 调用隐式的拷贝构造函数:FA(const FA& x){} 实现从源对象到目标对象逐个字节的复制
//FA FA2 = FA1; 和 FA FA3(FA1); 是一样的
/*******************深拷贝************************/
/*深拷贝例1*/ //对普通指针的拷贝
class Test
{
public:
int* p;
public:
Test(int x)
{
this->p = new int(x);
//this->p = &x; //x是临时的值,不能取到地址
}
~Test()
{
delete p;//释放指针-----在堆中申请的内存,需要手动释放
}
Test(const Test& a)
{
this->p = new int(*a.p);//新分配一块int类型内存空间,值为a对象的指针成员p的值,并将其赋值给b对象指针成员p.
}
};
int main()
{
Test a(10);
cout << *a.p << endl;
Test b = a;
return 0;
}
/*深拷贝例2*/ //对指针对象的拷贝
class DX
{
public:
int d;
DX(int x)
{
this->d = x;
}
};
class AAA
{
public:
int a;
DX* p;
AAA(int x,int y) //构造函数
{
this->a = x;
this->p = new DX(y);//使用构造函数时,给p指针分配内存地址
}
~AAA() //析构函数
{
delete p;
p = NULL;
}
AAA(const AAA& c) //自定义拷贝构造函数
{
this->a = c.a;//将A1.a的值赋值给A2.a
p = new DX(c.p->d);//新分配一块内存给A2.p指针,并调用DX的构造函数,将A1.p->d的值传递到A2.p对象中.
//使用拷贝构造函数时,给新对象A2中的指针p分配地址
}
};
int main()
{
AAA A1(2, 4);
AAA A2(A1);
cout << &A1.p->d << endl;//012FECA8 //在构造函数中分配地址 地址不同
cout << &A2.p->d << endl;//012FFFB0 //在拷贝构造函数中分配地址
system("pause");
return 0;
}
/********************错误实例***********************/
/*深拷贝例2*/ //对指针对象的拷贝 错误实例
class DX
{
public:
int d;
DX(int x)
{
this->d = x;
}
};
class AAA
{
public:
int a;
DX* p;
AAA(int x,int y)
{
this->a = x;
this->p = new DX(y);//初始化类内指针对象
}
~AAA()
{
delete p;
p = NULL;
}
};
int main()
{
AAA A1(2, 4);
AAA A2(A1);//使用默认拷贝构造函数 将指针A2.p = A1.p 进行了直接赋值,两个指针中都存放了相同的内存地址
cout << &A1.p->d << endl;//00C1ECA8 地址一样
cout << &A2.p->d << endl;//00C1ECA8 地址一样 在执行A2对象的析构函数时,指针p已经被销毁,再次执行会报错
system("pause");
return 0;
}