美文网首页C++ 杂记C++
C++ 深拷贝 浅拷贝 实例

C++ 深拷贝 浅拷贝 实例

作者: 赵者也 | 来源:发表于2017-01-18 22:23 被阅读207次

注意:本文中代码均使用 Qt 开发编译环境
//“浅拷贝”举例:

#include <QCoreApplication>
#include <QDebug>

class Point
{
public:
    Point(){
        X=Y=0;
        qDebug() << "Default Constructor called.";
    }

    Point(int xx,int yy){
        X=xx;
        Y=yy;
        qDebug() << "Constructor called.";
    }

    ~Point(){
        qDebug() << "Destructor called.";
    }

    int GetX() const {
        return X;
    }

    int GetY() const {
        return Y;
    }

    void Move(int x,int y){
        X=x;
        Y=y;
    }

private:
    int X,Y;
};

class ArrayOfPoints
{
public:
    ArrayOfPoints(int n){
        numberOfPoints = n;
        points = new Point[n];
    }

    ~ArrayOfPoints(){
        qDebug() << "Deleting...";
        numberOfPoints = 0;
        delete [] points;
    }

    Point& Element(int n){
        return points[n];
    }

private:
    Point *points;
    int numberOfPoints;
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    int number = 64;

    ArrayOfPoints pointArray1(number);          // 创建对象数组

    pointArray1.Element(0).Move(5,10);          // 通过指针访问数组元素的成员
    pointArray1.Element(1).Move(15,20);         // 通过指针访问数组元素的成员

    ArrayOfPoints pointArray2(pointArray1);     // 创建对象数组副本

    qDebug() << "Copy of pointsArray1: ";
    qDebug() << "Point_0 of array2: " << pointArray2.Element(0).GetX() << "," << pointArray2.Element(0).GetY();
    qDebug() << "Point_1 of array2: " << pointArray2.Element(1).GetX() << "," << pointArray2.Element(1).GetY();

    pointArray1.Element(0).Move(25,30);         // 通过指针访问数组元素的成员
    pointArray1.Element(1).Move(35,40);         // 通过指针访问数组元素的成员

    qDebug() << "After the moving of pointArray1: ";
    qDebug() << "Point_0 of array2: " << pointArray2.Element(0).GetX() << "," << pointArray2.Element(0).GetY();
    qDebug() << "Point_1 of array2: " << pointArray2.Element(1).GetX() << "," << pointArray2.Element(1).GetY();

    return a.exec();
}

//运行结果:

浅拷贝运行结果

//拷贝前后示意图:

拷贝前后示意图

从图中可以看出默认的拷贝构造函数将两个对象的对应数据项简单复制后,pointArray1 的成员 points 和 pointArray2 的成员 points 具有相同的值,也就是说两个指针指向同一个内存地址,表面上好像完成了复制,但是并没有形成真正的副本。因此当程序中移动 pointArray1 中的点时,也影响到了 pointArray2 。这种效果就是浅拷贝。

浅拷贝还有更大的弊病,在程序结束之前 pointArray1 和 pointArray2 的析构函数会被自动调用,动态分配的内存空间会被释放。由于两个对象共用了同一块内存空间,因此该空间被释放两次,于是导致运行时错误。解决办法是编写拷贝构造函数,实现“深拷贝”。

下面是对上述代码进行调整,加入拷贝构造函数之后,用于实现“深拷贝”的代码:

#include <QCoreApplication>
#include <QDebug>

class Point
{
public:
    Point(){
        X=Y=0;
        qDebug() << "Default Constructor called.";
    }

    Point(int xx,int yy){
        X=xx;
        Y=yy;
        qDebug() << "Constructor called.";
    }

    ~Point(){
        qDebug() << "Destructor called.";
    }

    int GetX() const {
        return X;
    }

    int GetY() const {
        return Y;
    }

    void Move(int x,int y){
        X=x;
        Y=y;
    }

private:
    int X,Y;
};

class ArrayOfPoints
{
public:
    ArrayOfPoints(int n){
        numberOfPoints = n;
        points = new Point[n];
    }

    ArrayOfPoints(ArrayOfPoints& pointsArray);  ///< 实现深拷贝

    ~ArrayOfPoints(){
        qDebug() << "Deleting...";
        numberOfPoints = 0;
        delete [] points;
    }

    Point& Element(int n){
        return points[n];
    }

private:
    Point *points;
    int numberOfPoints;
};

ArrayOfPoints::ArrayOfPoints(ArrayOfPoints& pointsArray){ ///< 实现深拷贝
    numberOfPoints = pointsArray.numberOfPoints;
    points = new Point[numberOfPoints];
    for (int i=0; i<numberOfPoints; i++) {
        points[i].Move(pointsArray.Element(i).GetX(), pointsArray.Element(i).GetY());
    }
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    int number = 64;

    ArrayOfPoints pointArray1(number);          // 创建对象数组

    pointArray1.Element(0).Move(5,10);          // 通过指针访问数组元素的成员
    pointArray1.Element(1).Move(15,20);         // 通过指针访问数组元素的成员

    ArrayOfPoints pointArray2(pointArray1);     // 创建对象数组副本

    qDebug() << "Copy of pointsArray1: ";
    qDebug() << "Point_0 of array2: " << pointArray2.Element(0).GetX() << "," << pointArray2.Element(0).GetY();
    qDebug() << "Point_1 of array2: " << pointArray2.Element(1).GetX() << "," << pointArray2.Element(1).GetY();

    pointArray1.Element(0).Move(25,30);         // 通过指针访问数组元素的成员
    pointArray1.Element(1).Move(35,40);         // 通过指针访问数组元素的成员

    qDebug() << "After the moving of pointArray1: ";
    qDebug() << "Point_0 of array2: " << pointArray2.Element(0).GetX() << "," << pointArray2.Element(0).GetY();
    qDebug() << "Point_1 of array2: " << pointArray2.Element(1).GetX() << "," << pointArray2.Element(1).GetY();

    return a.exec();
}

//运行结果:

深拷贝运行结果

相关文章

  • c/c++/c++11 浅拷贝和深拷贝

    目录 1 c++拷贝 1.1 拷贝构造函数1.2 浅拷贝1.3 深拷贝 2 c语言拷贝 2.1 浅拷贝2.2 深拷...

  • [C++之旅] 15 深拷贝与浅拷贝

    [C++之旅] 15 深拷贝与浅拷贝 拷贝构造函数分为深拷贝和浅拷贝两种方式 浅拷贝只是将被拷贝的对象的成员直接赋...

  • 浅拷贝、深拷贝

    浅拷贝、深拷贝 浅拷贝:使用一个已知实例对新创建实例的成员变量逐个赋值,这个方式被称为浅拷贝。 深拷贝:当一个类的...

  • C++ 深拷贝 浅拷贝 实例

    注意:本文中代码均使用 Qt 开发编译环境//“浅拷贝”举例: //运行结果: //拷贝前后示意图: 从图中可以看...

  • 原型模式

    简介 实现Cloneable接口,重写clone方法。要注意深拷贝和浅拷贝问题。 浅拷贝:新实例的...

  • 2019-08-12 vue 深拷贝 浅拷贝 只能输入3的

    只能输入3的倍数 什么是深拷贝?浅拷贝 ? 1.浅拷贝:浅拷贝是拷贝引用,拷贝后的引用都是指向同一个对象的实例,彼...

  • iOS深拷贝(MutableCopy)与浅拷贝(Copy)的区别

    深拷贝和浅拷贝的概念 iOS中有深拷贝和浅拷贝的概念,那么何为深拷贝何为浅拷贝呢?浅拷贝:浅拷贝并不拷贝对象本身,...

  • iOS - copy 与 mutableCopy

    一说到拷贝,就不得不提浅拷贝和深拷贝。 何谓浅拷贝?何谓深拷贝? 往简单的说: 浅拷贝:拷贝地址。 深拷贝:拷贝内...

  • iOS面试题-第二页

    11.深拷贝和浅拷贝的理解. 深拷贝;拷贝的内容. 浅拷贝:拷贝的指针. 深拷贝如: NSMutableDicti...

  • js浅拷贝深拷贝

    js浅拷贝,深拷贝的简单实现 基础数据 浅拷贝 深拷贝

网友评论

    本文标题:C++ 深拷贝 浅拷贝 实例

    本文链接:https://www.haomeiwen.com/subject/ddmbbttx.html