带你粗略了解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++中的深浅拷贝

相关文章:

你感兴趣的文章:

标签云: