帶你粗略了解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); // 對汽車信息進(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 = "無"; 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 << " 發(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)對很多問題,但是當(dāng)遇到指針的時(shí)候情況變得不同.下面給一個(gè)示例代碼:
#include "Car.h" #include <iostream> using namespace std; int main() { // 創(chuàng)建car_1對象 Car car_1("寶馬", 1); // 為car_1對象添加一個(gè)引擎 car_1.setEngine("寶馬", 1); // 創(chuàng)建car_2對象, 并且拷貝自car_1 Car car_2(car_1); // 輸出修改引擎前的兩個(gè)對象信息 cout << car_1.description() << endl; cout << car_2.description() << endl; // 修改引擎 car_2.setEngine("奔馳", 1); // 輸出修改引擎以后的兩個(gè)對象信息 cout << car_1.description() << endl; cout << car_2.description() << endl; return 0; }
三. 問題
當(dāng)我們對car_2對象的引擎進(jìn)行修改時(shí), 我們所期望的結(jié)果是僅僅只有car_2對象的引擎被修改,可是事實(shí)如此嗎?
結(jié)果顯示,并不是這樣,car_1對象的引擎和car_2對象的引擎都被改變了.
原因就是C++編譯器幫我們合成的拷貝構(gòu)造函數(shù)是一個(gè)淺拷貝,只是將變量的值拷貝過來,在Car類中的成員變量engine是一個(gè)指針變量,存放的是一個(gè)地址.在進(jìn)行拷貝構(gòu)造時(shí),就意味著car_1對象中engine變量和car_2對象中的engine變量存放的是同一個(gè)地址值(由于是new出來的對象, 所以地址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é)
本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
C語言中函數(shù)參數(shù)的入棧順序詳解及實(shí)例
這篇文章主要介紹了C語言中函數(shù)參數(shù)的入棧順序詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-02-02C++ vector的介紹及常見功能實(shí)現(xiàn)
這篇文章主要介紹了C++ vector的介紹及模擬實(shí)現(xiàn),vector在實(shí)際中非常的重要,但在實(shí)際中我們只要熟悉常見的接口就可以了,最重要的是理解他的底層原理,要能夠自己模擬實(shí)現(xiàn)出一個(gè)簡單的vector,本文結(jié)合示例代碼給大家詳細(xì)介紹,需要的朋友可以參考下2023-05-05C++實(shí)現(xiàn)旋轉(zhuǎn)掃描儀的示例代碼
旋轉(zhuǎn)掃描儀(Rotating?Scanner),也稱為旋轉(zhuǎn)掃描儀或圓形掃描儀,是一種用于獲取圖像和文檔的設(shè)備,下面就跟隨小編一起來學(xué)習(xí)一下如何使用C++實(shí)現(xiàn)旋轉(zhuǎn)掃描儀功能吧2024-02-02C++ 動(dòng)態(tài)內(nèi)存管理詳情解說
這篇文章主要介紹了C++ 動(dòng)態(tài)內(nèi)存管理詳情解說,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下,希望對你的學(xué)習(xí)有所幫助2022-07-07C語言驅(qū)動(dòng)開發(fā)內(nèi)核枚舉IoTimer定時(shí)器解析
這篇文章主要為大家介紹了C語言驅(qū)動(dòng)開發(fā)內(nèi)核枚舉IoTimer定時(shí)器解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10