tft每日頭條

 > 科技

 > c語言在内存中怎麼區分堆和棧

c語言在内存中怎麼區分堆和棧

科技 更新时间:2024-07-06 07:11:38

  拷貝構造函數

  今天和大家一起啊來學習一下c 中的拷貝構造函數,我們什麼時候 會用到這個函數呢?當你用一個對象去構造另外一個對象的時候,或者是說你用一個對象去初始化另外一個對象的時候就用到了我們的拷貝函數,例如:

  student stu(張三 student stu2=stu;

  上面使用對象stu去初始化我們新的對象stu2,這時候就涉及到對象的拷貝,如果這時候自己沒有寫拷貝函數,那麼程序就會選擇默認的拷貝函數,把stu的成員一個一個的拷貝給stu2。

  c語言在内存中怎麼區分堆和棧(編程中深拷貝與淺拷貝的區别)(1)

  深拷貝和淺拷貝

  我們剛剛提到了拷貝構造函數,是把已經初始化好的對象成員依次拷貝給新的對象,我們這樣想可能覺得比較方便,但是我們想一個另外的問題,那就是當一個對象在初始化的時候向系統申請了資源,那麼在拷貝給另外一個對象的時候會怎麼樣呢?我們來看一下代碼;

  #includeiostream #includestring.h using namespace std; class stu { private: int age; char *name; public: stu(int age, char *name) { this- this-name = new char[100]; strcpy(this-name,name); } void display()//打印函數 { cout姓名: 年齡: } void change(char * name)//修改姓名函數 { strcpy(this-name,name); } }; int main() { stu s1(18,張三 cout; s1.display(); couts1賦值給s2 stu s2=s1; cout; s2.display(); cout修改姓名後 s1.change(李四 cout; s1.display(); cout; s2.display(); return 0; }

  代碼結果分析

  c語言在内存中怎麼區分堆和棧(編程中深拷貝與淺拷貝的區别)(2)

  我們初始化好一個s1對象然後用它去初始化另外一個對象s2,經過打印函數我們可以看出來我們s1和s2的成員值都是一樣的,這時候我們做了一個事情,修改其中一個對象的姓名,然後在打印出來發現我們兩個對象的值都發生了改變,這我們想不符合我們的要求,我們希望每一個對象都是獨立的。那麼為什麼會出現這樣的情況呢?我們來分析一下拷貝函數在拷貝的時候系統内存情況

  c語言在内存中怎麼區分堆和棧(編程中深拷貝與淺拷貝的區别)(3)

  初始化時内存情況

  我們對象成員在拷貝的時候會複制原來對象的值給新的對象,但是如果原來的對象中有指針,就是說有申請過系統資源,那麼這時候拷貝就不是把原來s1對象裡面的*name的值給了s2對象對象中的*name指針,指針賦值意思就是說s1裡面的name指針和s2裡面的name指針值是一樣的,那麼換一句話說他們兩個nmae指針指向同一個内存地址,如下圖所示,這就為什麼我們修改其中一個對象裡面的名字另外一個對象的值也會更改的原因

  c語言在内存中怎麼區分堆和棧(編程中深拷貝與淺拷貝的區别)(4)

  深拷貝構造函數

  我們知道上面的構造函數在對象有系統資源比如說内存的時候是指向同一個地址,這不是我們想要的,所以我們引入了我們的深拷貝構造函數,就是在拷貝的時候我們當遇到需要資源的時候我們新的對象自己向系統申請單獨的資源,申請完後再完成複制拷貝。這樣兩個對象雖然值是一樣的但是我們并不是同一個資源,他們是獨立的,我們在剛剛的代碼上增加一個自己寫的拷貝構造函數來完成我們的深拷貝。

  stu(stu &s) { this-age=s.age; this-name = new char[100];//自己申請系統空間 strcpy(this-name,s.name); }

  深拷貝結果分析

  c語言在内存中怎麼區分堆和棧(編程中深拷貝與淺拷貝的區别)(5)

  從代碼中我們看出來經過添加的拷貝構造函數就實現了初始化後的對象都是獨立的,對其中一個對象的操作不會影響到其他的對象。

  總結

  我們每一個類裡面都有一個默認的拷貝構造函數,它是屬于淺拷貝,我們對象中有系統資源時我們需要自己寫一個深拷貝的構造函數這樣才會使得初始化出來的對象擁有獨立的特性。

  我們什麼時候會用到構造拷貝函數?

  1、用一個對象去構造另外一個對象。例如我們上面講到的:

  stu s1(18,張三 stu s2=s1;

  2、當我們把一個對象作為參數傳到函數中的時候。例如:函數void fun(student s);參數需要我們傳一個對象進去那麼我們在使用函數的時候我們把s1傳進去:fun(s1),這時候我們的實參s1和我們的函數形參s就形成了一個s=s1的情況這時候就用到我們的拷貝構造函數。

  3、返回一個靜态對象的時候。例如函數:

  stu fun() { static stu s(18,李四); return s; } stu s1=fun();//fun函數返回的對象複制給我們的s1這時候也用到我們的拷貝構造函數。

  結語

  我們的深拷貝與淺拷貝還有很多知識值得我們去深究,今天隻是以一個簡單的例子和代碼帶大家了解一下我們c 中的深拷貝與淺拷貝的區别,如果你有不一樣的看法可以說出來大家一起探讨學習一下,最後感謝你的的閱讀。

  ,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关科技资讯推荐

热门科技资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved