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
posted @ 2021-08-25 12:07  赶紧学习  阅读(136)  评论(0编辑  收藏  举报