tft每日頭條

 > 生活

 > c指針的作用

c指針的作用

生活 更新时间:2026-06-09 16:22:54

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-30
  • 怎麼用洗潔精做起泡膠
    1、首先,把起泡原膠倒入碗裡,起泡原膠作為底液,可以多倒一些。2、然後倒入洗潔精。3、可以按照自己的... 2023-06-30
  • 寒潮一共有多少種預警
    1、寒潮預警信号分四級,分别以藍色、黃色、橙色、紅色表示。2、寒潮藍色預警信号标準:48小時内最低氣... 2023-06-30
  • 電腦開機到鼠标重啟
    這是因為鼠标的驅動程序和其他軟件産生沖突導緻的。解決方法:更新鼠标驅動。工具:電腦。1、使用鼠标右鍵... 2023-06-30
  • 華為手機備忘錄放置在桌面步驟介紹
    1、雙指在手機屏幕上向内滑動。2、在底部位置點擊窗口小工具。3、然後點擊選擇備忘錄選項。4、選擇添加... 2023-06-30

热门生活资讯推荐

  • 生活 網吧老闆模拟器怎麼調中文
    1、首先我們安裝成功遊戲後,點擊遊戲的啟動圖标。2、遊戲啟動後,等待遊戲加載。3、進入遊戲的界面後,... 2023-06-30
  • 生活 1966年男性退休時間
    1、根據我國法律的相關規定,國家法定的企業職工退休年齡男性為60歲,即2026年退休;2、特殊情況的... 2023-06-30
  • 生活 一個手機怎麼下載兩個微信
    1、首先,打開手機,然後點擊手機桌面上的設置。2、然後進入設置後,再點擊應用和通知。3、然後點擊應用... 2023-06-30
  • 生活 租房布置注意事項
    1、不能隻圖便宜,一定要認真檢查房子是否是待拆遷的房子甚至是危樓。時下很多房主為了能收租更多的錢,将... 2023-06-30
  • 生活 自制酸奶面膜
    1、将牛奶放置溫暖的地方數日,使其乳酸大量發酵。将适量的發酵牛奶和面粉放在小缽中,調勻成濃稠的面粉糊... 2023-06-30
  • 生活 床闆一翻身老響怎麼辦
    1、鉚釘連接的地方發出聲響,重新釘上鉚釘;不是鉚釘的原因,用三角形固定,三角形的穩定性很好。2、在木... 2023-06-30
  • 生活 微波爐荷包蛋防爆做法
    1、安全方法:用微波爐做荷包蛋,在加熱之前,可用牙簽在荷包蛋上面紮幾個洞,使其在加熱時裡面的熱量可以... 2023-06-30
  • 生活 tcl是哪個國家的品牌
    1、tcl是中國的品牌。2、TCL集團股份有限公司(簡稱TCL或TCL集團)創立于1981年,經過三... 2023-06-30
  • 生活 六一兒童節風俗
    1、中國中華人民共和國正式定每年6月1日為國際兒童節。學校一般會為此組織相關的集體活動,并要求學生正... 2023-06-30
  • 生活 友誼保鮮小妙招
    1、要真誠的對待對方,這樣會讓你的朋友感覺到你的善意。誠懇會帶來彼此的信任,讓你們的心靈相通,這樣你... 2023-06-30

网友关注

  • 生活 團隊口号大全
    1、永不言退,我們是最好團隊。2、與其臨淵羨魚,不如退而織網。3、要鋪墊未來,先改造自己。4、相信本... 2023-06-30
  • 生活 文藝簡短無符号微博名
    1、既然琴瑟起2、齊眉念别離3、南岸青栀4、深情不及久伴5、藏于心6、任我鬧7、舊夢離裳8、回眸一笑... 2023-06-30
  • 生活 怎麼安慰一個心情不好的人
    1、分析為何心情不好。如果你不清楚對方為何心情不好的話,那麼你可能就沒辦法做到針對性的去勸解對方,讓... 2023-06-30
  • 生活 簡單好聽的男孩名字
    1、如奕、銘天、炜鈞、宏振、泰玮。2、文翰、智安、瀚尚、鑫達、波凱。3、國玮、鴻軒、葵玮、月澤、華韻... 2023-06-30
  • 生活 屏幕壓傷怎麼消除
    1、自動恢複:在一定程度上可以自動恢複。液晶屏裡面是有彈性的小球,在一定壓力下可以恢複,壓力太大了恢... 2023-06-30
  • 生活 糍粑可以放冰箱保存多久
    1、放冰箱儲存半個月作用。2、糍粑是可以放進冰箱進行保存的,在冰箱的低溫條件下,可以幫助抑制其細菌以... 2023-06-30
  • 生活 開服裝店要注意哪些
    1、是否需要請導購視情況而定。一開始創業的時候,可能自己手頭上的資金可能也不富裕,因此請不請人這就是一個問題了。如果覺得自己手頭上還可以,但是人手顯得不足,這時我們不妨可以請一個有經驗的導購來幫忙。如果手頭緊的話,那先自己累一點,等生意上去了再做決定。2、選址很重要。不管開什麼店,地址的選擇也是非常重要的。如果選擇了為為煙稀少的地方,或者定位的目标人群不在這一區活動的時候,這就顯得非常的被動了。因 2023-06-30
  • 生活 鴨肉怎麼越煮越硬
    1、鴨肉焯水時選擇了熱水下鍋,熱水會讓鴨肉變得更緊緻,血水不太容易泡出來,煮的時候就會越煮越硬。2、... 2023-06-30
  • 生活 卧室适合養什麼花
    1、虎尾蘭,有很多花卉都适合放在卧室養殖,一般卧室放什麼花有助睡眠最好,虎尾蘭就是其中之一,将虎尾蘭... 2023-06-30
  • 生活 狐臭止汗的方法
    1、善用止汗産品一般止汗産品有舒緩的作用,可以偶爾使用。但是在挑選止汗劑的時候,也要多多留意成分,最... 2023-06-30
  • 生活 洗衣機洗衣服絞在一起處理方法
    1、塑料瓶。用洗衣機洗衣服的時候,先将衣服放進洗衣機,然後丢兩個空礦泉水瓶進去,再放水開始洗衣服,洗... 2023-06-30
  • 生活 hxd網用語什麼意思
    1、Hxd是網絡用語好兄弟的縮寫,在網絡上被經常使用,比如求資源時,總會來一句“hxd,gkd”。2... 2023-06-30
  • 生活 短裙太松了該怎麼辦
    1、巧用腰帶。即使新買的短裙,有時候還是會出現不貼身的現象。因此,這時候隻需要一條小小的腰帶或者皮帶... 2023-06-30
  • 生活 冬天油漆幹的慢怎麼解決
    1、環境溫度濕度異常:室内的溫度過低,濕度太大,達不到幹燥的條件。解決辦法:在室内太陽燈,提高室内的... 2023-06-30
  • 生活 電話打通不顯示鍵盤是怎麼回事
    若通話中不出現數字鍵盤,建議:1、通話過程中-點擊屏幕上的“鍵盤”,即可打開數字鍵盤。2、若無法調出... 2023-06-30
  • 生活 學信網怎麼解綁微信号
    可以登錄學信網,然後在個人中心解綁。1、百度網頁的搜索欄中輸入【學信網】,搜索一下,找到【學信網】的... 2023-06-30
  • 生活 微信支付自動扣費怎麼關閉
    1、打開微信并點擊右下角的“我”選項。2、然後我們點擊進入到“支付”界面。3、接下來點擊支付界面右上... 2023-06-30
  • 生活 固體面膜的正确使用方法
    1、先準備一個塑料小勺和小盆,用小勺取出一部分的固體面膜,再将面膜放進塑料小盆中,用勺子将面膜進行攪... 2023-06-30
  • 生活 關于過年的說說
    1、關于過年的說說:(1)一切不以收壓歲錢為目的的走親戚都是浪費時間。(2)今年過節不收禮,收禮隻收... 2023-06-30
  • 生活 冰箱怎麼清潔出水槽
    1、用細長鐵絲通一通排水孔,将污物通出排水孔後水既可以流出。2、冰箱集水槽正常情況下不會有積水存在,... 2023-06-30
  • 生活 長虹電視遙控器怎麼k歌
    1、按遙控器上的麥克風鍵,對着遙控器發出語音指令即可。2、長虹Q3T的遙控器能夠K歌,長虹Q3T支持... 2023-06-30
  • 生活 湖北省博物館開放時間
    1、每個星期的星期二至星期日9:00-17:00(15:30停止入場),每周的周一閉館,(國家法定節... 2023-06-30
  • 生活 抖音一瓜未平一瓜又起什麼意思
    1、一瓜未平一瓜又起,網絡流行語,指上一個瓜還沒有了解清楚,沒有弄明白,結果馬上又有新的一個瓜出現了... 2023-06-30
  • 生活 和菠蘿長得一樣的水果叫什麼
    1、和菠蘿長得一樣的水果是鳳梨。2、鳳梨是熱帶的著名水果之一,其實它和菠蘿不僅長得很像,而且就連科屬... 2023-06-30
  • 生活 無線網絡卡頓怎麼解決
    1、由于路由器長期使用,會導緻路由器本身的硬件發熱,運行緩慢,加速硬件老化。所以我們定期讓路由器斷電... 2023-06-30
  • 生活 威猛先生重油污清洗劑怎麼用
    威猛先生重油污清洗劑的使用方法:将重油污清洗劑對準油污噴灑即可。油污是油在揮發過程中長久積累形成的污垢。家庭廚房裡一般容易出現油污的積累。去除油污的方法有:1、草木灰除油污:盆、碗、碟上沾了油污,可用草木灰或鋸末擦拭,然後用淘米水洗淨,再用清水沖洗即可。2、廢茶葉除油污:餐具沾上過多的油污,可用廢茶... 2023-06-30
  • 生活 男孩祛痘痘的好方法
    1、男生長痘痘的大部分原因是與飲食分不開的,特别是經常要出席應酬的上班族男士,大吃大喝的都是一些高熱... 2023-06-30
  • 生活 南方養什麼羊好
    1、波爾山羊養殖:波爾山羊是世界上肉用性能最好的山羊品種,它原産于南非,具有個體大、生長速度快、耐粗... 2023-06-30
  • 生活 招工前臨時工能算工齡嗎
    1、可以。2、職工檔案資料有履曆記錄,并有工資表證明的,被國企、集體企業招工前最後一次本單位做臨時工... 2023-06-30
  • 生活 微信群發助手會建群嗎
    1、微信群發助手不會建群。2、進入微信,點擊右下角的【我】。3、進入我,點擊【設置】。4、進入設置,... 2023-06-30