tft每日頭條

 > 生活

 > c指針的作用

c指針的作用

生活 更新时间:2026-01-12 10:30:50

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-06-29
  • 手镯佩戴技巧
    1、首先要注意手镯的大小尺寸,如果手镯過大,很易将手镯碰壞。如果過小,則會導緻血液不通。2、手镯的款... 2023-06-29
  • 實名制diss是什麼意思
    1、實名diss的意思是在diss别人的時候報出實名,是一種非常嚣張的挑釁行為。2、意思是不僅要怼,... 2023-06-29

热门生活资讯推荐

  • 生活 風水學禁忌熱門标簽
    1、家裡的鏡子太多鏡子在風水來說它很陰寒容易會招邪,那若是家中鏡子太多則會造成夫妻耗财,也就是指這對... 2023-06-29
  • 生活 什麼是商品的淘寶客
    1、淘寶客,是一種按成交計費的推廣模式,也指通過促銷賺取利潤的人。2、隻要淘寶客戶從淘寶促銷區獲得商... 2023-06-29
  • 生活 晚安真正的意思你弄懂了嗎
    第一、一種客套并不是所有的晚安都是多麼的深情款款,有些晚安是一種客套,比如說和自己的客戶交流到很晚,或者是自己的部門經理之類,那麼臨睡之前會客客氣氣的說句晚安。第二、表現溫柔這是男女剛剛相識,彼此都有點意思的時候想要通過晚安來表達的一種含義,臨下線之前,溫柔的來一句晚安,表達自己的溫柔、細膩、第三、... 2023-06-29
  • 生活 麻屋子紅帳子白胖子分别指什麼
    這是一個描述花生的謎語:“麻屋子,紅帳子,裡面住着個白胖子。”麻屋子是果皮,是由子房壁發育而成;紅帳子是種皮,是由珠被發育而成;白胖子是指胚,是由受精卵發育而成。花生,原名落花生,是我國産量豐富、食用廣泛的一種堅果,又名長生果、泥豆等。屬薔薇目,豆科一年生草本植物,莖直立或匍匐,長30~80厘米,翼瓣與龍骨瓣分離,莢果長2~5厘米,寬1~1.3厘米,膨脹,莢厚,花果期6~8 2023-06-29
  • 生活 幹冰能放冰箱冷凍室嗎
    1、冰箱冷凍室最低溫度為零下18度,而保存幹冰需要零下78.5度,把幹冰放在冰箱裡,幹冰會融化、氣化、升華,體積膨脹1000多倍,爆炸沖破冰箱。所以不建議放到冰箱裡儲存,如果是少量幹冰,建議用普通的泡沫箱存儲,但是儲存時間不長,大概48小時以内會揮發成氣體。2、幹冰是固态的二氧化碳,在6250.5498千帕壓力下,把二氧化碳冷凝成無色的液體,再在低壓下迅速凝固而得到。現在幹冰已經廣泛應用到了許多領 2023-06-29

网友关注

  • 生活 立flag是下決心嗎
    1、是。立flag是指說一句振奮的話,或者立下一個要實現的目标。簡單地說,一個人被他自己說的話打臉了... 2023-06-29
  • 生活 母螃蟹黃裡面黑的是什麼
    1、母螃蟹黃裡面黑的是蟹的胃。2、蟹黃旁邊的黑色膠狀物是螃蟹的胃,也被稱為蟹尿包,位于背殼前緣中央,... 2023-06-29
  • 生活 寶寶睡袋怎麼選
    1、首先看品牌,大品牌的睡袋質量有保證,口碑也好,寶寶用安全可靠。其次看質量,質量包含兩方面,一是面... 2023-06-29
  • 生活 垃圾填埋對什麼産生最直接的影響
    1、爆炸事故和火災。填埋釋放氣體由大量甲烷和二氧化碳組成,當CH4在空氣中的濃度達到5%~15%,易... 2023-06-29
  • 生活 螃蟹放冰塊能被冰死麼
    螃蟹是冷血動物,耐低溫,因此螃蟹在溫度較低時會打開自我保護機制,即冬眠現象,若短時間的冷凍,比如讓螃蟹在冰層中待24小時左右,大多數的螃蟹在解凍之後還存活。若螃蟹在冰層中待的時間超過了48小時,大部分螃蟹會開始死亡,其死亡原因與低溫和缺氧有直接關系。螃蟹屬軟甲綱,十足目,是甲殼類動物,身體被硬殼保護着,靠鰓呼吸。在生物分類學上,它與蝦、龍蝦、寄居蟹是同類動物。絕大多數種類的螃蟹生活在海裡或近海區, 2023-06-29
  • 生活 衛生間有蟑螂的原因
    蟑螂出現的原因:蟑螂喜歡溫暖、潮濕、食物豐富和多縫隙的場所栖居,人生活和居住的地方都具有這些條件,所以蟑螂就成了侵害千家萬戶的衛生害蟲。蟑螂有很多渠道可以來到家中,比如通過排水管、門窗縫隙等,或随貨物攜帶進入家庭。蟑螂繁殖速度:蟑螂的繁殖是有性繁殖與無性繁殖相結合,一隻成熟的雌蟑螂每隔7天即可産出一隻含有14到40粒卵的卵鞘,卵鞘在20到37度之間孵化,溫度越高孵化時間越短,一隻雌蟑螂一年可繁殖近 2023-06-29
  • 生活 打鹵面的鹵子做法
    1、準備食材:木耳15克、黃花菜30克、豬肉末80克、雞蛋2個、食用油、鹽1勺、生抽1大勺、蚝油2大勺、水澱粉、麻油。2、用涼水把黃花菜和木耳泡發。3、木耳洗淨切細絲,黃花菜洗淨切兩段,香蔥蔥白和适量姜末一起爆香用。香蔥葉切末拌面用。4、熱鍋,放入适量食用油,先把肉末炒至變色,再放入蔥末姜末爆香。5、放入切好的木耳和黃花菜,加入2勺生抽1勺蚝油,1小勺鹽。6、放入沒過食材的溫開水,蓋蓋子煮5-6分 2023-06-29
  • 生活 好聽又簡單的微信昵稱
    1、羅羅貝兒2、小紅帽3、燈下孤影4、愛冒險5、水中月6、過氣美圖社7、陳獨秀8、陳甜9、柒七10、... 2023-06-29
  • 生活 白棉布發黃有什麼辦法變白
    1、鹽+小蘇打準備好鹽、小蘇打和1000毫升的清水,然後将鹽和小蘇打混合進清水中,把發黃的棉布放進去泡半小時,按照正常的洗滌流程洗一遍,曬幹即可。2、淘米水+橙子皮在做飯的時候留下淘米水,然後剝一個橙子或者是橘子,取一個鍋,然後将淘米水和橙子皮大火煮開,然後倒進盆裡等水溫降到40℃以下,把發黃的棉布放進去泡15-20分鐘,用肥皂搓洗幾遍,黃漬就慢慢消失不見了。3、漂白劑将漂白劑倒入盆中并浸泡棉布半 2023-06-29
  • 生活 畢業季教師節送什麼禮物
    1、藝術筆筒:非常有藝術氣息的筆筒是非常适合老師的一款禮物,而且你還可以根據老師的喜好挑選一款别具古... 2023-06-29
  • 生活 大溪地在哪
    1、大溪地在南太平洋。2、塔希提島,港台譯為大溪地,是法屬波利尼西亞向風群島中的最大島嶼,位于南太平... 2023-06-29
  • 生活 為什麼小目标容易成功
    1、小而合适的目标能更容易讓你達成。假設你是個追求上進的人,但你的目标很大很困難,慢慢地你會發現自己... 2023-06-29
  • 生活 vivo手機帶紅外線功能
    vivo具有紅外功能,原因如下:1、因為vivo手機的紅外傳感器在通過紅外發射遇到物體的反射并接收到... 2023-06-29
  • 生活 為什麼會一直單身的原因
    第一、完美主義有的人覺得愛情是至高無上的,看了太多小說中的愛情,在現實生活中,也要尋找自己心中最完美的意中人,但小說是虛構的,在現實中總也找不到令自己滿意的人。第二、相信可遇不可求有的人相信,愛情是可遇不可求的,相信一見鐘情,但在現實生活中,巧遇實在太少,不可能出現奇迹,所以,就一直耽誤下去,一直是... 2023-06-29
  • 生活 土蜂蜜帶苦味怎麼回事
    土蜂蜜的純度高,沒有經過過濾和消毒,各種蜂蜜的翅膀、蜂體和一些排洩物會殘留其中,因此在食用時會帶有一些苦味,但不會影響蜂蜜的營養價值,可以放心食用。蜂蜜是蜜蜂從開花植物的花中采得的花蜜在蜂巢中經過充分釀造而成的天然甜物質。氣味清香濃郁,味道純真甜美。蜜蜂從植物的花中采取含水量約為75%的花蜜或分泌物,存入自己第二個胃中,在蜜蜂體内多種轉化的作用下,再由工蜂将轉化後花蜜或分泌物存貯到巢洞中,用蜂蠟密 2023-06-29
  • 生活 麻雀的壽命
    2023-06-29
  • 生活 一個人生活的經典句子
    1、一個人,在外面,雖然孤獨,但也有孤獨的快樂。學會享受孤獨,2、這時候,或許就會懷戀一個人的獨處,... 2023-06-29
  • 生活 女人如何從婚外情中走出來
    第一、跟第三者一刀兩斷。如果你打算結束這段婚外情的話,那麼請跟對方一刀兩斷吧,最好不要有任何的聯系了。不然你心裡總是放心不下對方,又如何從婚外情中解脫出來呢。第二、認真擔負起家庭的責任。我們的責任意識應該要加強,擺正好自己的位置,做好自己的本分之事。畢竟如若我們想要回歸家庭的話,就應該履行我們做為妻... 2023-06-29
  • 生活 為什麼海裡有鹽
    目前科學界對鹽分的來源主要有有兩個觀點,一是降水形成徑流的過程中對陸地上的土壤、岩石的侵蝕作用将含鹽礦物質帶入河流,最終彙入海洋;二是海底本身的地質活動(火山噴發、海底熱液等)會溶解一部分鹽分到海水中。海水是海中或來自海中的水。海水是流動的,對于人類來說,可用水量是不受限制的。海水是名符其實的液體礦産,平均每立方公裡的海水中有3570萬噸的礦物質,世界上已知的100多種元素中,80%可以在海水中找 2023-06-29
  • 生活 電腦上的東西删了可以複原嗎?
    1、東西删了可以複原。方法一:回收站恢複法。不小心删除文件以後,在桌面點開回收站,找到删除的文件後點... 2023-06-29