tft每日頭條

 > 生活

 > c指針的作用

c指針的作用

生活 更新时间:2026-01-18 19:38:14

C 是我平時的工作中用的最多的語言,Python基本是在學習的時候會用,有時候也會用它來寫一寫腳本。所以,今天準備摻一點C 的知識。

智能指針是C 11标準中的其中一個特性。本文可能需要有一點C 語言的基礎。不過盡量用簡潔的文字來介紹。如果對C 語言不了解又想學習的話,需要C 學習資料的後台私聊我哦,都是我之前自己學習整理出來的資料。感覺還可以。

在開發C 程序的時候,我們使用new動态的從堆中申請内存,然後使用delete将這段内存釋放。使用new申請的内存C 編譯器是不會自動釋放的。因此,如果我們使用了new來申請内存,但是沒有使用delete釋放内存,就會造成内存洩漏。如果申請内存的操作是在一個循環中的話,就會不斷的造成内存洩漏,最終導緻内存不足,程序崩潰。這是很嚴重的問題。

顯然,讓程序員來管理内存的釋放問題是很繁瑣的。有的時候,我們甚至不知道應該在什麼時候使用delete來釋放内存。比如說在編寫比較複雜的多線程程序的時候,申請的内存可能會有多個線程同時訪問,可能你自己都無法确定應該合适釋放這一塊内存。因此,如果能讓C 編譯器來自動完成内存的分配和釋放,那程序員的壓力就小很多了。

智能指針内存的分配和釋放都是由C 編譯器自動完成的。這就是智能指針存在的意義,我們可以将繁瑣的内存管理問題交給C 編譯器,而将精力放在我們的業務邏輯上。

智能指針的類型

C 11中提出的智能指針有三種類型:shared_ptr、unique_ptr、weak_ptr。使用這三種智能指針的時候需要包含庫memory。

(1) shared_ptr

shared_ptr(就是一種指針)管理内存的機制如下:shared_ptr采用引用計數的方式來管理所指向的對象。什麼意思呢?舉個例子:

現在有一個對象dog,有一個shared_ptr指向它, 此時它的引用計數為1;當有一個新的shared_ptr也指向了dog,那麼它的引用計數自動加1,為1;當指向了dog的shared_ptr了離開了它的作用域,引用計數減1,又變為1了。當引用技術為0時(也就是說所有指向dog的shared_ptr都離開了作用域),dog占用的内存自動釋放。

還不理解?沒關系,看一段代碼:

#include #include #include class Dog { private: std::string name_; public: Dog(std::string name) { std::cout << "Dog is created." << name << std::endl; name_ = name; } Dog() { std::cout << "Nameless dog created." << std::endl; name_ = "nameless"; } ~Dog() { std::cout << "dog is destroyed: " << name_ << std::endl; } void bark() { std::cout << "Dog " << name_ << " rules" << std::endl; } }; void foo() { //創建一個指針下面兩種方式都可以 //shared_ptr p(new Dog("Gunner")); std::shared_ptr p = std::make_shared("Gunner"); //p.use_count==1 std::cout << "p->use_count() = " << p.use_count() << std::endl; { std::shared_ptr p2 = p; //p.use_count==2 std::cout << "p->use_count() = " << p.use_count() << std::endl; p2->bark(); } //離開大括号時,p2的作用域結束,p的引用計數減1 //p.use_count==1 std::cout << "p->use_count() = " << p.use_count() << std::endl; p->bark(); } int main() { foo(); }

首先要注意下面幾點:

  • 創建shared_ptr的方式有兩種
    • 直接使用new關鍵字的方式: shared_ptr p(new Dog("Gunner"));
    • 使用make_shared的方式:shared_ptr p = make_shared("Gunner");
  • shared_ptr、make_shared都是在命名空間std當中,為了避免初學者誤會,我直接寫成了std::shared_ptr、std::make_shared的方式,而沒有使用using namespace std;

運行結果如下:

c指針的作用(C11中的智能指針)1

怎麼理解内存自動釋放了呢: 在foo()函數執行結束之後,智能指針p離開了作用域,它的引用計數減為0了,然後創建的Dog的對象的析構函數自動調用了,輸出: dog is destroyed: Gunner。

上面有幾個C 中的重要概念,稍微做一些解釋:

  • 命名空間:命名空間也稱為名字空間,最通俗的理解就是一個命名的容器,一個空間内的變量、函數、類等的命名不可以相同,但是不同空間的命名可以相同。std是C 編譯器的命名空間,C 标準庫中的函數或者對象都是在命名空間std中定義的,所以我們要使用标準函數庫中的函數或對象都要使用std來限定。
  • 析構函數: 析構函數和構造函數可以認為是一對函數。構造函數在創建一個類的對象時被自動調用,通常用來做一些初始化的工作。析構函數與構造函數相反,當對象結束其生命周期,如對象離開它的作用域,系統自動執行析構函數。析構函數往往用來做“清理善後” 的工作(例如在建立對象時用new開辟了一片内存空間,delete會自動調用析構函數後釋放内存)。

(2) unique_ptr

unique是獨一無二的意思。unique_ptr的涵義也是相似的,它表達的是一種獨占的思想,與shared_ptr最大的區别是unique_ptr不共享它的指針,某個時刻隻能有一個unique_ptr指向一個給定的對象。

創建unique_ptr的方式如下:

  • 使用new關鍵字:std::unique_ptr ptr(new Example(1));
  • 使用std::make_unique:std::unique_ptr ptr = std::make_unique(1);

常用的函數說明:

  • get() : 返回被管理對象的指針
  • release() : 返回指向被管理對象的指針,并釋放所有權
  • swap() : 交換被管理對象

使用示例:

#include #include #include using namespace std; class Example { public: Example(int param = 0) { number = param; cout << "Example: " << number << endl; } ~Example() { cout << "~Example: " << number << endl; } void test_print() { cout << "in test print: number = " << number << endl; } void set_number(int num) { number = num; } private: int number; }; void test1() { unique_ptr ptr1 = make_unique(1); if (ptr1.get()) { ptr1.get()->test_print(); ptr1->set_number(2); (*ptr1).test_print(); } unique_ptr ptr2(new Example(20)); ptr2->test_print(); ptr1.swap(ptr2); cout << "ptr1和ptr2交換管理對象" << endl; ptr1->test_print(); ptr2->test_print(); } int main() { test1(); return 0; }

運行結果:

c指針的作用(C11中的智能指針)2

(3) weak_ptr

std::weak_ptr是一種智能指針。它對被std::shared_ptr管理的對象存在非擁有性(弱)引用。weak_ptr是為了配合shared_ptr而引入的一種智能指針,它不具有普通指針的行為,沒有重載運算符*和->,其最大作用在于協助shared_ptr工作,像旁觀者那樣觀測資源的使用情況。weak_ptr可以從一個shared_ptr或者另weak_ptr對象構造,獲得資源的觀測權。但weak_ptr沒有共享資源,它的構造不會引起指針引用計數的增加。

使用weak_ptr的成員函數use_count()可以觀測資源的引用計數,另一個成員函數expired()的功能等價于使得use_count==0,表示被觀測的資源(也就是shared_ptr管理的資源)已經不複存在。weak_ptr有一個重要的成員函數lock()可以從被觀測的shared_ptr中獲得一個可用的shared_ptr對象,從而操作資源。

weak_ptr被設計用來避免std::shared_ptr的循環引用。

什麼是循環引用問題,下面舉個例子說明一下:

假設現在有兩個類A、B,創建了兩個智能指針shared_ptr ptr_A、shared_ptr ptr_B分别指向了A、B兩個類的對象a、b。A中有個shared_ptr指向b,B中有個shared_ptr指向a。

下面我們看一下ptr_A、ptr_B的引用計數分别是多少:

  • ptr_A.use_count = 2
  • ptr_B.use_count = 2

然後程序結束時,ptr_A、ptr_B都離開了它的作用域,引用計數減為1,所以a、b占用的内存不會釋放。這就是shared_ptr的缺陷。

下面可以從一個例子中看一下:

#include #include class foo; class Test { public: Test() { std::cout << "construct.." << std::endl; } void method() { std::cout << "welcome Test.." << std::endl; } ~Test() { std::cout << "destruct.." << std::endl; } public: std::shared_ptr fooptr; }; class foo { public: foo() { std::cout << "foo construct.." << std::endl; } void method() { std::cout << "welcome Test foo.." << std::endl; } ~foo() { std::cout << "foo destruct.." << std::endl; } public: std::shared_ptr testptr; }; int main() { // 循環引用 測試 Test* t2 = new Test(); foo* foo1 = new foo(); std::shared_ptr shptr_Test(t2); std::shared_ptr shptr_foo(foo1); std::cout << "shptr_Test RefCount: " << shptr_Test.use_count() << std::endl; std::cout << "shptr_foo RefCount: " << shptr_foo.use_count() << std::endl; shptr_Test->fooptr = shptr_foo; shptr_foo->testptr = shptr_Test; std::cout << "shptr_Test RefCount: " << shptr_Test.use_count() << std::endl; std::cout << "shptr_foo RefCount: " << shptr_foo.use_count() << std::endl; return 0; }

運行結果如下:

c指針的作用(C11中的智能指針)3

在程序結束時,Test類和foo類的析構函數并沒有調用。

使用weak_ptr改進的程序如下:

#include #include class foo; class Test { public: Test() { std::cout << "construct.." << std::endl; } void method() { std::cout << "welcome Test.." << std::endl; } ~Test() { std::cout << "destruct.." << std::endl; } public: std::weak_ptr fooptr; }; class foo { public: foo() { std::cout << "foo construct.." << std::endl; } void method() { std::cout << "welcome Test foo.." << std::endl; } ~foo() { std::cout << "foo destruct.." << std::endl; } public: std::weak_ptr testptr; }; int main() { // 循環引用 測試 Test* t2 = new Test(); foo* foo1 = new foo(); std::shared_ptr shptr_Test(t2); std::shared_ptr shptr_foo(foo1); std::cout << "shptr_Test RefCount: " << shptr_Test.use_count() << std::endl; std::cout << "shptr_foo RefCount: " << shptr_foo.use_count() << std::endl; shptr_Test->fooptr = shptr_foo; shptr_foo->testptr = shptr_Test; std::cout << "shptr_Test RefCount: " << shptr_Test.use_count() << std::endl; std::cout << "shptr_foo RefCount: " << shptr_foo.use_count() << std::endl; return 0; }

運行結果如下:

c指針的作用(C11中的智能指針)4

可以看到析構函數自動調用了,内存正常釋放。

今天的内容就到這兒了。如果對我的推、文有興趣,歡迎轉、載分、享。也可以推薦給朋友關注哦。隻推幹貨,甯缺毋濫。

,

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

查看全部

相关生活资讯推荐

  • 酵素梅子能減肥嗎
    1、單純靠酵素梅子減肥很難達到理想的效果,目前臨床上科學的減肥方法還是通過控制飲食,适當鍛煉。要清淡... 2023-07-07
  • 臨時額度還有6天到期是什麼意思
    1、臨時額度,顧名思義額度隻是暫時的,到了使用期限信用卡就會回到原始額度。不同的銀行信用卡臨時額度的使用期限都不同,一般是一到三個月。臨時額度還有6天到期,就是說明額度使用期限還有6天,6天之後就不能用銀行給的信用卡的臨時額度了。2、臨時額度失效後,使用到的臨時額度(超出固定額度的部分)不享受循環信... 2023-07-07
  • 桂花盆栽怎麼養
    1、土壤。盆栽養殖桂花要用微酸性土壤,它不适合在堿性土中生長。在栽培前,應該對土壤進行簡單的消毒,這樣在養護時,才能減少植株被病蟲危害的幾率。2、澆水。給它澆水不要固定頻次,要根據土壤的濕潤狀态适當澆水。最好時等盆土變幹後,再進行澆水。在夏季植株需水量比較大,可适當多澆些;但到了秋冬季節則需控制澆水... 2023-07-07
  • 畢業代表班級送什麼給老師比較好
    1、送老師紀念禮物集體送老師一件具有永久紀念價值的擺件是非常有意義的,可以在上面刻上班級名稱和日期,... 2023-07-07
  • 天津市生活垃圾分為哪四類
    1、天津生活垃圾分為廚餘垃圾、可回收物、有害垃圾、其他垃圾四大類。2、天津鼓勵通過積分兌換、獎勵等多... 2023-07-07

热门生活资讯推荐

  • 生活 清洗牡蛎方法
    1、活生蚝:生蚝外殼鋒利,我們最好戴手套處理,然後用刷子把外殼上的泥沙清洗掉。2、生蚝肉:如果購買的... 2023-07-07
  • 生活 二字網名幹淨古風生僻字
    1、妩媚2、鎖心3、憐星4、甜芋5、追随6、绾卿7、難擁8、舊傷9、敷衍10、囚愛11、等待12、歉... 2023-07-07
  • 生活 中國國歌叫什麼名字
    1、中國的全稱為中國人民共和國,中國國歌名為《義勇軍進行曲》。2、《義勇軍進行曲》完整歌詞:起來!不... 2023-07-07
  • 生活 悟空問答收益怎麼計算
    1、現在的一般是閱讀粉絲收益,粉絲閱讀回答比較多,你收益就越高。但是前提是那個回答是原創的,有收益的... 2023-07-07
  • 生活 标間是什麼意思
    1、标準間是指卧室、工作區、會客區同在一室,并且有單獨衛生間的房間。标準間分為标準雙人間和标準大床間... 2023-07-07
  • 生活 喝不完的魚湯怎麼保存
    1、冰箱保存。2、喝不完的魚湯最好的保存方法是湯底不要放鹽之類的調味料,煮好湯用幹淨的勺子盛出當天要... 2023-07-07
  • 生活 vivo手機怎樣去水滴
    1、全面屏機型的“劉海”、水滴位置搭載了攝像頭、聽筒及傳感器等,所以是不能隐藏。2、若有部分軟件按鍵... 2023-07-07
  • 生活 藝術塗料店怎麼引流
    1、第一步:打造一款藝術塗料電視背景牆的包裝服務,材料和人工成本在300元左右,市場定價1980元;... 2023-07-07
  • 生活 浴室瓷磚怎麼選
    1、挑選衛生間所用的瓷磚,首先要近距離的觀察瓷磚的做工還要聽瓷磚的敲擊聲來判斷瓷磚的質量更重要的是還... 2023-07-07
  • 生活 碳十三和碳十四的區别
    1、碳十三是碳的穩定同位素之一,它們主要的區别在于性質的不同,碳十三性質是比較穩定的,而碳十四具有微... 2023-07-07

网友关注

  • 生活 女士适合盤玩什麼手串
    1、小葉紫檀,小葉紫檀同料108顆佛珠通體清澈發亮4圈繞腕設計,使女生手腕看出去更加修長,小葉紫檀散... 2023-07-07
  • 生活 西洋參種植方法
    1、種植西洋參時要選擇偏酸性的腐殖土壤,且要有好的灌溉資源。2、種前先整地耕地,還要噴灑消毒液對土壤... 2023-07-07
  • 生活 最新蘆筍種植方法
    1、種植地的選擇:土壤條件更好。要選擇土壤肥沃,土壤深層,肥料和保水性強,滲透性好的土壤2、定植田的... 2023-07-07
  • 生活 進門看見發财樹好嗎
    1、進門看見發财樹好。2、發财樹由于它的觀賞性高,并且它有很好的風水意義,在家裡擺放也是有很多講究,... 2023-07-07
  • 生活 女人什麼嘴型最好看最标準
    身為口紅控的妹子可不在少數,每天塗這赤橙黃綠青藍紫的口紅色号出門,還不是希望自己的唇部看起來更加美麗。日常生活當中的護理必不可少,對于唇部的護理非常的重要,但是最重要的還是天生麗質的唇形。實際上中國人更偏愛的還是一些櫻桃小嘴,除此以外,還有幾種很受歡迎的标準嘴型,并不是歐美的性感大唇,是更偏向于溫柔... 2023-07-07
  • 生活 新疆十大特産
    1、和田美玉。新疆自古以來以産美玉而聞名,其中又以和田玉最負盛名。其質地溫潤細膩,呈脂肪光澤,其聲若... 2023-07-07
  • 生活 怎樣才能捉住蜂王?
    1、找蜂王,蜂巢底部有下凹通風口一般就有蜂王。2、用煙熏蜂巢,清理蜂群。3、用專門的蜜蜂囚王籠抓蜂王... 2023-07-07
  • 生活 送什麼禮物給老師如何挑選禮物給老師
    第一、鋼筆鋼筆是一種書寫工具,有金筆和銥金筆兩種,現在鋼筆已經成分身份的象征,因此,也可以送老師一根鋼筆。第二、賀卡如果臨近畢業的話,也可以每個人送給老師一張賀卡,賀卡上寫上感謝老師的話。第三、留言冊班級可以合買一本留言冊,然後每個人都寫上想對老師說的話,然後再收集起來送給老師。第四、個性變色杯現在... 2023-07-07
  • 生活 iphone6splus升級ios1...
    1、iphone6splus升級ios13不會卡,但會有一系列的小問題出現,不建議升級。2、系統流暢... 2023-07-07
  • 生活 如何跟孩子有效溝通
    1、如果要和孩子溝通,一定要選擇适合自己孩子的方法和技巧,一定要平等的對待自己的孩子,将自己的孩子當... 2023-07-07
  • 生活 u盤顯示格式化才能打開怎麼辦
    1、解決辦法:系統修複邏輯錯誤;點擊你的U盤盤符右鍵,菜單裡點擊屬性;然後點擊工具一欄,點擊開始檢查... 2023-07-07
  • 生活 自行車液壓碟刹調節方法
    1、首先把碟刹夾器和車架連接的螺絲松掉,讓夾器可以自由晃動。2、用橡皮筋或繩子把後輪刹車把拉緊,讓夾... 2023-07-07
  • 生活 12月25日是什麼節日
    1、12月25日是聖誕節(Christmas)又稱耶誕節,譯名為“基督彌撒”,它源自古羅馬人迎接新年... 2023-07-07
  • 生活 熱敏紙怎麼保存
    1、熱敏紙打印後,避免陽光直射,在光線越暗的地方,熱敏紙的字迹保存期就越長。2、避免熱敏紙接觸潮濕環... 2023-07-07
  • 生活 花甲螺怎麼做
    1、切好所有食材,洗淨花甲螺備用。2、鍋内入油倒入花甲螺翻炒,然後加料酒翻炒。3、待花甲螺全部開口之後加入生姜大蒜小米椒翻炒。4、之後加鹽、老抽、味精翻炒均勻。5、最後加香蔥翻炒上鍋。 2023-07-07
  • 生活 日本人吃味精嗎
    1、日本人不愛吃味精,做飯經常用高湯。但是喜歡吃仙貝或者膨化食品這些制作過程中添加了味精的東西。2、... 2023-07-07
  • 生活 綠色通道中綠色的含義
    1、綠色有準許行動之意。因為交通訊号中綠色代表可行。綠色通道是其引申詞,意為快捷方便,一路暢通無阻。... 2023-07-07
  • 生活 冬天氣泵結冰怎麼處理
    1、氣泵冬天凍冰,用戶可以将氣泵放在室内防止凍冰。氣泵主要分為電動氣泵和手動氣泵,腳動氣泵。電動氣泵... 2023-07-07
  • 生活 拖鞋怎麼解決磨腳
    1、用白酒擦拭,将酒精倒在幹淨的毛巾上,然後在磨腳部位輕輕擦拭。2、等拖鞋變得柔軟時基本就不會磨腳了... 2023-07-07
  • 生活 金子的鑒定方法
    1、掂重量法:鑒定黃金真假最快的方法之一就是掂重量,黃金與其他貴金屬的比重大約在19比32,因此黃金... 2023-07-07
  • 生活 把熱水放進冰箱冰凍會怎麼樣
    1、影響儲存效果,冰箱内部應該維持4℃左右,這樣,冰箱裡儲藏的食物才能放得久。熱的東西直接放進冰箱,... 2023-07-07
  • 生活 蘋果手機視頻播放自動暫停怎麼辦
    1、系統的問題,把手機上重要的資料先備份下,然後恢複出廠設置。2、下載的第三方軟件問題,關機狀态下,... 2023-07-07
  • 生活 蝙蝠的過冬方法是什麼
    1、蝙蝠通常在洞裡過冬。它冬眠時新陳代謝的能力降低,呼吸和心跳每分鐘僅有幾次,血流減慢,體溫降低到與... 2023-07-07
  • 生活 銀行會提前回收貸款是什麼原因
    1、貸款嚴重逾期。如果借款的人不能按時足額還款,或者是連續嚴重逾期,那麼,這種人自然得不到銀行的信任。銀行為了降低信貸風險,會要求貸款人一次性償還剩餘的貸款本息。比如房貸逾期超過3個月,車貸逾期超過3個月等等。2、隻還本金不還利息。同樣也屬于沒有按時還款,銀行不是慈善機構,貸款收取利息是應該的。如果... 2023-07-07
  • 生活 如何在excel中求和
    1、首先打開相應的Excel表格,找到所要求和的行(或列),将單元格定位到這行數據的和所要放置的位置... 2023-07-07
  • 生活 網上審車怎麼審
    1、首先點擊進入所在城市的車管所網站,接着點擊網上辦理服務。然後選擇項目類型免檢車核發檢驗标志(六年... 2023-07-07
  • 生活 香椿葉怎麼保存能放到冬季
    1、冷藏法。香椿芽洗淨,用沸水汆燙,控幹水分後分成小份,用保鮮紙包裹幾層,密封放置在保鮮袋中,然後入冰箱冷凍,随吃随化凍,椿葉仍然嫩綠芳香,用這樣的方法可以保鮮幾個月之久。香椿汆燙,可以有效除去其含有的亞硝酸亞,還有利于維生素C的留存,有資料顯示,凍凍2個月時,汆燙過的香椿中維生素C含量相當于鮮品的... 2023-07-07
  • 生活 光貓重新插入路由器無法聯網
    1、按照運營商的要求設置好撥号連接,單機接運營商光貓之類的設備,撥号上網後進行ping測運營商的網關... 2023-07-07
  • 生活 飛機上能帶多少液體
    1、一般規定,旅客可攜帶液體、壓縮氣體及凝膠狀物體登機,但是每名旅客隻可攜帶每項總容量不超過100毫... 2023-07-07
  • 生活 自己裝修真的能省錢嗎
    1、自己裝修的話,在裝修初期你就得自己去建材市場買材料,不過,建材品類繁多,而且挑選也有很多技巧,如果不具備足夠的挑選知識,很有可能會挑選到劣質産品,進而影響到後續的使用。2、不管你在裝修的時候是選擇找施工隊還是找熟人裝修,如果沒有簽訂正規的合同來限制他們,很有可能在裝修的時候出現馬馬虎虎的情況,甚... 2023-07-07