C++封装 之 拷贝构造函数
拷贝构造函数
思考
- 拷贝构造函数的定义?
- 什么时候调用拷贝构造函数?
- 拷贝构造函数如何实现?
拷贝构造函数回顾:
-
定义:
拷贝构造函数与普通构造函数基本相同,只是参数上有严格要求:(1)要加const ;(2)传入的是引用,且是一个对象; -
如果没有自定义拷贝构造函数,系统会自动生成一个默认的拷贝构造函数。
-
当采用直接初始化(Student st1)或复制初始化(Student st2=st1 或Student st2(st3) )实例化对象时,系统自动调用拷贝构造函数;
-
函数调用传递参数时也会调用拷贝构造函数。
-
拷贝构造函数的参数是确定的,不能重载。
浅拷贝 和 深拷贝
- 只是将数据成员的值进行了简单的拷贝,称为浅拷贝;
- 不仅仅是做值的拷贝,堆中内存也要拷贝,称为深拷贝。
实例1(浅拷贝)
定义一个Array类
- 数据成员为m_iCount ,
- 成员函数包括构造函数、拷贝构造函数、析构函数、数据封装函数
- 通过此示例体会浅拷贝原理
copy_demo1.cpp源码:
#include<iostream>
#include<stdlib.h>
using namespace std;
/****************** 定义Array类 ******************************/
class Array{
public:
Array();
Array(const Array &arr); //拷贝构造函数定义
~Array();
void setCount(int count);
int getCount();
private:
int m_iCount;
};
/****************** Array类的函数实现 ******************************/
Array::Array(){
cout << "Array()" << endl;
}
Array::Array(const Array &arr){ //拷贝构造函数实现
m_iCount = arr.m_iCount;
cout << "Array &" << endl;
}
Array::~Array(){
cout << "~Array()" << endl;
}
void Array::setCount(int count){
m_iCount = count;
}
int Array::getCount(){
return m_iCount;
}
/****************** 测试主函数 ******************************/
int main(){
Array arr1;
arr1.setCount(9);
cout << "arr1.m_iCount = "<< arr1.getCount() << endl;
Array arr2(arr1); // 用arr1拷贝实例化arr2,调用拷贝构造函数
cout << "arr2.m_iCount = "<<arr2.getCount() << endl;
system("pause");
return 0;
}
运行结果:
Array()
arr1.m_iCount = 9
Array &
arr2.m_iCount = 9
实例2(深拷贝)
- 增加数据成员m_pArr
- 并增加m_pArr地址查看函数,同时改造构造函数、拷贝构造函数和析构函数,
- 通过此示例体会浅拷贝原理
copy_demo2.cpp源码
#include<iostream>
#include<stdlib.h>
using namespace std;
/****************** 定义Array类 ******************************/
class Array{
public:
Array(int count);
Array(const Array &arr); //拷贝构造函数定义
~Array();
void setCount(int count);
int getCount();
void printAddr(); //数据成员*m_pArr的封装函数,打印地址
void printArr(); //打印m_pArr所指向地址的值
private:
int m_iCount;
int *m_pArr; //增加数据成员*m_pArr
};
/****************** Array类的函数实现 ******************************/
Array::Array(int count){
m_iCount = count;
m_pArr = new int[m_iCount]; //前提是m_iCount是一个确切的值,所以构造函数要传入一个参数count
for(int i=0; i<m_iCount; i++) //赋值(为了方便打印)
m_pArr[i] = i;
cout << "Array()" << endl;
}
/*
Array::Array(const Array &arr){ //拷贝构造函数实现(浅拷贝)
m_pArr = arr.m_pArr; //两个指针指向同一块内存(理论上是错误的)
m_iCount = arr.m_iCount;
cout << "Array &" << endl;
}
*/
Array::Array(const Array &arr){ //拷贝构造函数实现(深拷贝)
m_iCount = arr.m_iCount;
m_pArr = new int[m_iCount]; //先给当前指针分配内存
for(int i=0; i<m_iCount; ++i){ //再做内存拷贝
m_pArr[i] = arr.m_pArr[i];
}
cout << "Array &" << endl;
}
Array::~Array(){
delete []m_pArr; //
m_pArr = NULL; //
cout << "~Array()" << endl;
}
void Array::setCount(int count){
m_iCount = count;
}
int Array::getCount(){
return m_iCount;
}
void Array::printAddr(){ ///
cout << "m_pArr point to " << m_pArr << endl;
}
void Array::printArr(){
for(int i=0; i<m_iCount; i++)
cout<<"m_pArr["<<i<<"] = "<< m_pArr[i]<<endl;
}
/****************** 测试主函数 ******************************/
int main(){
Array arr1(9);
Array arr2(arr1); // 用arr1拷贝实例化arr2,调用拷贝构造函数,使用深拷贝之后,两个指针指向不同内存地址
//arr1.setCount(9); //构造函数中已经传入了参数9,所以不需要arr1.setCount(9)了
arr1.printAddr();
arr2.printAddr(); //两个指针会指向同一块内存,同一块内存不能释放两遍,两个对象都执行析构函数就会发生运行时错误
arr1.printArr();
arr2.printArr();
system("pause");
return 0;
}
运行结果:
Array()
Array &
m_pArr point to 0x711920
m_pArr point to 0x711960
m_pArr[0] = 0
m_pArr[1] = 1
m_pArr[2] = 2
m_pArr[3] = 3
m_pArr[4] = 4
m_pArr[5] = 5
m_pArr[6] = 6
m_pArr[7] = 7
m_pArr[8] = 8
m_pArr[0] = 0
m_pArr[1] = 1
m_pArr[2] = 2
m_pArr[3] = 3
m_pArr[4] = 4
m_pArr[5] = 5
m_pArr[6] = 6
m_pArr[7] = 7
m_pArr[8] = 8