帶你粗略了解C++中的深淺拷貝
一. 背景
首先看這樣一個(gè)問題,在Car類中聚合了Engine類

二. 代碼實(shí)現(xiàn)
下面給出類Car與類Engine的定義
Car.h
#ifndef COPY__CAR_H_
#define COPY__CAR_H_
#include "Engine.h"
#include <string>
using namespace std;
class Car {
public:
// 構(gòu)造函數(shù)
Car();
Car(string brand, int version);
~Car();
// 添加或者修改一個(gè)引擎
void setEngine(string engine_brand, int engine_version);
// 對(duì)汽車信息進(jìn)行描述
string description() const;
private:
string brand; // 品牌
int version; // 型號(hào)
Engine *engine; // 引擎
};
#endif //COPY__CAR_H_
Car.cpp
#include "Car.h"
#include <sstream>
Car::Car() {
this->brand = "無(wú)";
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 = "無(wú)";
this->version = 0;
}
Engine::Engine(string brand, int version) {
this->brand = brand;
this->version = version;
}
Engine::~Engine() {
}
string Engine::description() const {
stringstream result;
result << " 發(fā)動(dòng)機(jī)品牌:" << brand << " 發(fā)動(dòng)機(jī)版本:" << version;
return result.str();
}
在大部分情況下,在類中不去實(shí)現(xiàn)拷貝構(gòu)造函數(shù)是可行的,C++編譯器會(huì)幫助我們自動(dòng)生成一個(gè)拷貝構(gòu)造函數(shù). 并且這個(gè)拷貝構(gòu)造函數(shù)足以應(yīng)對(duì)很多問題,但是當(dāng)遇到指針的時(shí)候情況變得不同.下面給一個(gè)示例代碼:
#include "Car.h"
#include <iostream>
using namespace std;
int main() {
// 創(chuàng)建car_1對(duì)象
Car car_1("寶馬", 1);
// 為car_1對(duì)象添加一個(gè)引擎
car_1.setEngine("寶馬", 1);
// 創(chuàng)建car_2對(duì)象, 并且拷貝自car_1
Car car_2(car_1);
// 輸出修改引擎前的兩個(gè)對(duì)象信息
cout << car_1.description() << endl;
cout << car_2.description() << endl;
// 修改引擎
car_2.setEngine("奔馳", 1);
// 輸出修改引擎以后的兩個(gè)對(duì)象信息
cout << car_1.description() << endl;
cout << car_2.description() << endl;
return 0;
}
三. 問題
當(dāng)我們對(duì)car_2對(duì)象的引擎進(jìn)行修改時(shí), 我們所期望的結(jié)果是僅僅只有car_2對(duì)象的引擎被修改,可是事實(shí)如此嗎?

結(jié)果顯示,并不是這樣,car_1對(duì)象的引擎和car_2對(duì)象的引擎都被改變了.
原因就是C++編譯器幫我們合成的拷貝構(gòu)造函數(shù)是一個(gè)淺拷貝,只是將變量的值拷貝過來(lái),在Car類中的成員變量engine是一個(gè)指針變量,存放的是一個(gè)地址.在進(jìn)行拷貝構(gòu)造時(shí),就意味著car_1對(duì)象中engine變量和car_2對(duì)象中的engine變量存放的是同一個(gè)地址值(由于是new出來(lái)的對(duì)象, 所以地址engine變量中存放的值處于堆空間). 如圖所示.(地址是瞎編的)

四. 解決方法
解決方法就是:手動(dòng)實(shí)現(xiàn)拷貝構(gòu)造函數(shù),實(shí)現(xiàn)深拷貝,如圖所示.

在Car.cpp文件中添加如下代碼 :
Car::Car(const Car &other) {
this->brand = other.brand;
this->version = other.version;
engine = new Engine(other.brand, other.version);
}
主函數(shù)不變,得到如下結(jié)果:

總結(jié)
本篇文章就到這里了,希望能給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
C語(yǔ)言深入分析浮點(diǎn)型數(shù)據(jù)存儲(chǔ)
使用編程語(yǔ)言進(jìn)行編程時(shí),需要用到各種變量來(lái)存儲(chǔ)各種信息。變量保留的是它所存儲(chǔ)的值的內(nèi)存位置。這意味著,當(dāng)您創(chuàng)建一個(gè)變量時(shí),就會(huì)在內(nèi)存中保留一些空間。您可能需要存儲(chǔ)各種數(shù)據(jù)類型的信息,操作系統(tǒng)會(huì)根據(jù)變量的數(shù)據(jù)類型,來(lái)分配內(nèi)存和決定在保留內(nèi)存中存儲(chǔ)什么2022-08-08
C++文件的數(shù)據(jù)寫入和文件的數(shù)據(jù)讀取的方法實(shí)現(xiàn)
本文主要介紹了C++文件的數(shù)據(jù)寫入和文件的數(shù)據(jù)讀取的方法實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06
C++實(shí)現(xiàn)對(duì)RGB圖片進(jìn)行編碼的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何利用得到的RGB信息重新對(duì)RGB圖片進(jìn)行編碼,以及對(duì)其他圖片如BMP所得到的RGB信息進(jìn)行編碼從而得到*.jpg文件,感興趣的可以了解一下2023-05-05
如何實(shí)現(xiàn)循環(huán)隊(duì)列
本文主要介紹了C語(yǔ)言循環(huán)隊(duì)列的實(shí)現(xiàn),對(duì)于數(shù)據(jù)結(jié)構(gòu)與算法的研究有所幫助,需要的朋友可以參考下2015-07-07
一文詳解C++關(guān)鍵字nullptr及與NULL的區(qū)別
這篇文章主要給大家詳細(xì)介紹了C++關(guān)鍵字nullptr,及?NULL與nullptr的區(qū)別,文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下2023-06-06
C語(yǔ)言 strftime 格式化顯示日期時(shí)間的實(shí)現(xiàn)
下面小編就為大家?guī)?lái)一篇C語(yǔ)言 strftime 格式化顯示日期時(shí)間的實(shí)現(xiàn)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2016-12-12

