带你粗略了解C++中的深浅拷贝

 更新时间:2021年08月19日 10:37:08   作者:supermario19  
这篇文章主要给大家介绍了关于c++中深浅拷贝以及写时拷贝实现的相关资料,文中通过示例代码介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面跟着小编来一起学习学习吧

一. 背景

首先看这样一个问题,在Car类中聚合了Engine类

二. 代码实现

下面给出类Car与类Engine的定义

Car.h

#ifndef COPY__CAR_H_
#define COPY__CAR_H_
#include "Engine.h"
#include <string>
using namespace std;
class Car {
 public:
  // 构造函数
  Car();
  Car(string brand, int version);
  ~Car();
  // 添加或者修改一个引擎
  void setEngine(string engine_brand, int engine_version);
  // 对汽车信息进行描述
  string description() const;
 private:
  string brand; // 品牌
  int version; // 型号
  Engine *engine; // 引擎
};
#endif //COPY__CAR_H_

Car.cpp

#include "Car.h"
#include <sstream>
Car::Car() {
  this->brand = "无";
  this->version = 0;
  this->engine = nullptr;
}
Car::Car(string brand, int version) {
  engine = nullptr;
  this->brand = brand;
  this->version = version;
}
Car::~Car() {
}
void Car::setEngine(string engine_brand, int engine_version) {
  if (engine) {
    delete engine;
  }
  engine = new Engine(engine_brand, engine_version);
}
string Car::description() const {
  stringstream result;
  result << "品牌:" << brand << " 版本:" << version << engine->description();
  return result.str();
}

Engine.h

#ifndef COPY__ENGINE_H_
#define COPY__ENGINE_H_
#include <string>
using namespace std;
class Engine {
 public:
  Engine();
  Engine(string brand, int version);
  ~Engine();
  string description() const;
 private:
  string brand;
  int version;
};
#endif //COPY__ENGINE_H_

Engine.cpp

#include "Engine.h"
#include <sstream>
Engine::Engine() {
  this->brand = "无";
  this->version = 0;
}
Engine::Engine(string brand, int version) {
  this->brand = brand;
  this->version = version;
}
Engine::~Engine() {
}
string Engine::description() const {
  stringstream result;
  result << " 发动机品牌:" << brand << " 发动机版本:" << version;
  return result.str();
}

在大部分情况下,在类中不去实现拷贝构造函数是可行的,C++编译器会帮助我们自动生成一个拷贝构造函数. 并且这个拷贝构造函数足以应对很多问题,但是当遇到指针的时候情况变得不同.下面给一个示例代码:

#include "Car.h"
#include <iostream>
using namespace std;
int main() {
  // 创建car_1对象
  Car car_1("宝马", 1);
  // 为car_1对象添加一个引擎
  car_1.setEngine("宝马", 1);
  // 创建car_2对象, 并且拷贝自car_1
  Car car_2(car_1);
  // 输出修改引擎前的两个对象信息
  cout << car_1.description() << endl;
  cout << car_2.description() << endl;
  // 修改引擎
  car_2.setEngine("奔驰", 1);
  // 输出修改引擎以后的两个对象信息
  cout << car_1.description() << endl;
  cout << car_2.description() << endl;
  return 0;
}

三. 问题

当我们对car_2对象的引擎进行修改时, 我们所期望的结果是仅仅只有car_2对象的引擎被修改,可是事实如此吗?

结果显示,并不是这样,car_1对象的引擎和car_2对象的引擎都被改变了.

原因就是C++编译器帮我们合成的拷贝构造函数是一个浅拷贝,只是将变量的值拷贝过来,在Car类中的成员变量engine是一个指针变量,存放的是一个地址.在进行拷贝构造时,就意味着car_1对象中engine变量和car_2对象中的engine变量存放的是同一个地址值(由于是new出来的对象, 所以地址engine变量中存放的值处于堆空间). 如图所示.(地址是瞎编的)

四. 解决方法

解决方法就是:手动实现拷贝构造函数,实现深拷贝,如图所示.

在Car.cpp文件中添加如下代码 :

Car::Car(const Car &other) {
  this->brand = other.brand;
  this->version = other.version;
  engine = new Engine(other.brand, other.version);
}

主函数不变,得到如下结果:

总结

本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注脚本之家的更多内容!

相关文章

  • C语言深入分析浮点型数据存储

    C语言深入分析浮点型数据存储

    使用编程语言进行编程时,需要用到各种变量来存储各种信息。变量保留的是它所存储的值的内存位置。这意味着,当您创建一个变量时,就会在内存中保留一些空间。您可能需要存储各种数据类型的信息,操作系统会根据变量的数据类型,来分配内存和决定在保留内存中存储什么
    2022-08-08
  • C++文件的数据写入和文件的数据读取的方法实现

    C++文件的数据写入和文件的数据读取的方法实现

    本文主要介绍了C++文件的数据写入和文件的数据读取的方法实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • C++实现对RGB图片进行编码的示例代码

    C++实现对RGB图片进行编码的示例代码

    这篇文章主要为大家详细介绍了如何利用得到的RGB信息重新对RGB图片进行编码,以及对其他图片如BMP所得到的RGB信息进行编码从而得到*.jpg文件,感兴趣的可以了解一下
    2023-05-05
  • 如何实现循环队列

    如何实现循环队列

    本文主要介绍了C语言循环队列的实现,对于数据结构与算法的研究有所帮助,需要的朋友可以参考下
    2015-07-07
  • C++实现的归并排序算法详解

    C++实现的归并排序算法详解

    这篇文章主要介绍了C++实现的归并排序算法,结合实例形式详细分析了归并排序算法的原理、实现步骤、操作技巧与使用方法,需要的朋友可以参考下
    2017-05-05
  • 一文详解C++关键字nullptr及与NULL的区别

    一文详解C++关键字nullptr及与NULL的区别

    这篇文章主要给大家详细介绍了C++关键字nullptr,及 NULL与nullptr的区别,文中通过代码示例介绍的非常详细,需要的朋友可以参考下
    2023-06-06
  • C/C++ extern关键字用法示例全面解析

    C/C++ extern关键字用法示例全面解析

    这篇文章主要为大家介绍了C/C++ extern关键字用法示例全面解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • C语言 strftime 格式化显示日期时间的实现

    C语言 strftime 格式化显示日期时间的实现

    下面小编就为大家带来一篇C语言 strftime 格式化显示日期时间的实现。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-12-12
  • 基于C++自动化编译工具的使用详解

    基于C++自动化编译工具的使用详解

    本篇文章是对C++中自动化编译工具的使用进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • C++使用easyx实现打砖块游戏

    C++使用easyx实现打砖块游戏

    这篇文章主要为大家详细介绍了C++使用easyx实现打砖块游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05

最新评论