tft每日頭條

 > 生活

 > c指針的作用

c指針的作用

生活 更新时间:2026-09-12 20:49:43

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-01
  • 怎麼練習打字速度
    1、選擇适合自己的輸入法。有些人喜歡打五筆,有些人喜歡打拼音或者是其他的輸入法,其實不管哪種輸入法,... 2023-07-01
  • 打印機有色差怎麼辦
    1、打印色塊進行墨水測試看效果,然後和色樣對比,看到底是不是墨水的原因。2、在打印機裡面有個噴頭校準... 2023-07-01
  • 鐵婚是結婚多少年
    1、中國6年是鐵婚,因中國有七年之癢一說,而鐵會氧化生鏽,可能喻指夫妻之間的感情今年會不太穩固,而6... 2023-07-01
  • 塞爾達名字是什麼意思
    1、塞爾達有兩種意思。一種是指《塞爾達傳說》系列的簡稱,另一種意思則是指塞爾達(日文名:ゼルダ,英文... 2023-07-01

热门生活资讯推荐

  • 生活 培養皿怎樣做合格
    1、把要用到的試劑瓶放到工作區合适的位置,并将即将要用的試劑瓶蓋子松開;2、把培養皿放在工作區的中心... 2023-07-01
  • 生活 給别人擔保影響自己公積金貸款嗎
    1、如果公積金管理中心不知道給别人做住房擔保的情況,就不會有影響。2、如果公積金管理中心知道了有為别人做擔保的情況,可以和被擔保人一起到所在住房公積金管理中心,在查詢了被擔保人的還款有無逾期後,如果還款情況正常,就可以按照程序申請住房公積金貸款并且貸款額度不受影響。3、但如果被擔保人的還款情況不正常... 2023-07-01
  • 生活 羊皮毛一體怎麼清洗和保養?
    1、首先取出一盆清水,将毛巾放入到水盆中浸泡一下。2、然後再用手搓洗一下毛巾。3、接下來再将毛巾平鋪... 2023-07-01
  • 生活 蜂王漿怎麼提取
    1、蜂王漿是由工蜂王漿腺中分泌出的一種乳狀物質,用于飼喂蜜蜂幼蟲和蜂王,順帶一提,隻吃王漿幾天的幼蟲... 2023-07-01
  • 生活 四川野釣鯉魚鲫魚配方
    1、野戰藍鲫30%+鲫魚套餐30%+天源紅鲫20%+天源黃鲫20%,餌水比1:1.1拉餌,1:1是搓... 2023-07-01
  • 生活 乳膠漆開裂的正确處理方法
    1、把表面裂縫凸起的地方用小刀刮掉,把牆邊整體打磨平整,光滑,然後再買一些乳膠漆,在牆面裂縫的地方再... 2023-07-01
  • 生活 安裝硬盤前消除靜電的最簡單方法
    1、電源内部絕緣不良或空氣潮濕引起的輕微漏電。機箱外殼在吸收電源和其他配件産生的電磁波時産生的感應電... 2023-07-01
  • 生活 qq贊不了别人的說說
    1、首先可能這是因為你的QQ近期有頻繁點贊的情況,導緻QQ被禁贊,點贊不能正常顯示,刷新以後就會消失... 2023-07-01
  • 生活 過年的時候吃雞代表什麼寓意
    1、過年的時候吃雞寓意着“吉祥”。因為“雞”字,通“吉”字,簡單通俗易懂的道理,深入人們的心裡,過年... 2023-07-01
  • 生活 QQ網名怎麼添加表情符号
    1、在電腦登陸并進入我們的扣扣好友列表窗口。2、進入到好友列表後,随便打開一個與好友聊天的窗口。3、... 2023-07-01

网友关注

  • 生活 小白鞋用什麼方法洗掉污漬
    1、檸檬法小白鞋髒得最快的地方,最不好清理的,應該就是鞋邊了。檸檬汁中含有大量檸檬酸鹽,屬于弱酸性液... 2023-07-01
  • 生活 甘蔗種怎麼存放
    1、地面貯藏法:在蔗田及附近,選擇避風處,耙松表土,澆濕地表,将甘蔗堆放成2米左右高的堆,上面鋪蓋鮮... 2023-07-01
  • 生活 耐高溫材料都有哪些
    1、耐高溫材料分成耐火材料和耐熱材料。2、耐火材料有鎢、钼、钽、铌、釩、鉻、钛、锆等難熔金屬以及稀土... 2023-07-01
  • 生活 成長勵志的句子經典語錄
    1、你要做一個不動聲色的大人了。不準情緒化,不準偷偷想念,不準回頭看。去過自己另外的生活。你要聽話,... 2023-07-01
  • 生活 紅米note7pro怎麼設置紅包提醒
    1、第一步,在紅米Note7Pro手機的屏幕上,找到手機的【系統軟件】文件夾,并點擊打開。2、第二步... 2023-07-01
  • 生活 微信狀态怎麼更換背景圖
    1、打開微信的“我”界面,點擊“狀态”。2、選擇你想設置的狀态,随便寫點什麼,然後點擊“拍攝”。3、... 2023-07-01
  • 生活 結束海邊之旅心情說說
    1、任她潮起潮落,花開花落,我隻管,面朝大海,春暖花開。日出日落,月圓月缺,潮來潮去,花開花謝,生命... 2023-07-01
  • 生活 4種簡單的粽子包法
    1、三角粽的包法:取2張粽葉剪取尾部硬杆;葉子正反相貼毛面相對;在三分之一處折成漏鬥;在漏鬥中加入糯... 2023-07-01
  • 生活 105國道起點和終點
    起點為北京,終點為廣東珠海。105國道(或“國道105線”、“G105”)是在中國的一條國道,起點為北京,終點為廣東珠海,全程2717千米。這條國道經過北京、天津、河北、山東、河南、安徽、湖北、江西和廣東9個省份。國道:國道是指具有全國性政治、經濟意義... 2023-07-01
  • 生活 在花店怎麼挑君子蘭
    1、在選購君子蘭時首先要從整體外觀觀察,比如形态特征,植株的高矮,葉片的新鮮度,以及生長狀況,有沒有... 2023-07-01
  • 生活 ps/2鍵盤不能用怎麼辦
    1、首先打開本地磁盤,右鍵“此電腦”-“管理”。2、在打開的頁面内點擊左側的“設備管理器”,可以在右... 2023-07-01
  • 生活 頭皮屑多怎麼辦小妙招
    1、啤酒去屑法:用溫熱啤酒少許将頭發濡濕,15分鐘後用清水沖洗,最後用普通洗發膏洗發。每日3次,一般... 2023-07-01
  • 生活 鑽石怎樣分等級
    1、鑽石主要根據4C标準即顔色、切工、淨度和重量來劃分等級。鑽石顔色從無色透明到黃色分為D到Z等23... 2023-07-01
  • 生活 藤壺是什麼東
    1、藤壺是雌雄同體,大多行異體受精,生殖期間用能伸縮的細管将精子送入别的藤壺中使卵受精。受精卵經曆變... 2023-07-01
  • 生活 烤面筋紅油冬天上凍怎麼辦
    1、烤面筋紅油冬天上凍隻需要使室内的溫度升高在10攝氏度以上,就會恢複原狀。2、烤面筋紅油即便凍住了... 2023-07-01
  • 生活 租房大忌
    1、不貪便宜。低于行情之屋子,必有不利市場及租方的條件。如屋子在風水上不利于住人,曾經死過人或結構有... 2023-07-01
  • 生活 藍牙鍵盤的鼠标怎麼使用
    1、首先藍牙鼠标和鍵盤是屬于一體的一個系統,不能單獨的去使用鼠标。2、一般的鼠标,他都會有一個類似u... 2023-07-01
  • 生活 華為p30
    1、第一步打開華為p30,點擊桌面的設置。2、第二步進去華為p30設置之後,點擊顯示和亮度。3、第三... 2023-07-01
  • 生活 農用二氯異氰尿酸鈉在種植上的應用
    1、農用二氯異氰尿酸鈉為白色粉末狀或顆粒狀的固體,是氧化性殺菌劑中殺菌最為廣譜、高效、安全的消毒劑,... 2023-07-01
  • 生活 黃金項鍊清洗技巧
    1、黃金項鍊自己清洗的話就放于純淨水中,輕微簡單刷一下即可,然後晾幹放首飾盒。2、建議定期将金飾返回... 2023-07-01
  • 生活 單價怎麼計算
    1、單價=價格總額/商品數量。2、含稅單價=不含稅單價+不含稅單價*稅率。3、實際工作中,要有數量才... 2023-07-01
  • 生活 如何拔牙
    1、選擇合适的時間段拔牙,月經期、哺乳期能拔牙,最好下午15點前拔牙。2、拔牙後,前兩天不要吃刺激性... 2023-07-01
  • 生活 紅小豆煮水怎麼是黑色的
    1、顔色變深屬于正常現象。2、紅小豆煮水之後其顔色會變深,這是因為紅小豆的外皮為紅色,其裡面含有一定... 2023-07-01
  • 生活 電視盒子怎麼看電視直播
    1、打開電視自帶的應用商店,或者使用手機連接電視,打開電視互動app。2、連接成功後,切換到應用界面... 2023-07-01
  • 生活 元宵節送給領導的祝福語
    1、祝願你節日快樂,生活大步向前。2、正月十五吃湯圓,夢想之月為你圓。祝元宵快樂!3、元宵節,願你快... 2023-07-01
  • 生活 如何清洗變髒了的不鏽鋼擦球
    1、用胡蘿蔔加雞蛋殼清洗。具體做法如下:2、準備材料:胡蘿蔔、雞蛋殼。3、首先切一段胡蘿蔔,做飯炒菜... 2023-07-01
  • 生活 案的古義
    1、案是一個漢字,讀作àn,古稱案幾,本義是指木制的盛食物的矮腳托盤,亦指長形的桌子或架起來代替桌子... 2023-07-01
  • 生活 大冒險爆笑懲罰方法
    1、對窗外大喊:我好寂寞啊。2、找個在場異性拍合照發到朋友圈,配文這是我的男/女朋友。3、自摸自己身... 2023-07-01
  • 生活 夢見自己懷孕是什麼預兆
    1、對于沒有戀愛的小姐姐,做到自己懷孕的夢,如果夢境是快樂的,說明你真的很想得到幸福的愛情,就體現出... 2023-07-01
  • 生活 怎樣去巴基斯坦做生意
    巴基斯坦外貿市場開發可通過以下8個渠道和方法:1、入駐B2B平台據很多外貿老鳥反映:巴基斯坦客戶喜歡... 2023-07-01