tft每日頭條

 > 生活

 > c指針的作用

c指針的作用

生活 更新时间:2025-06-04 11:57:06

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每日頭條,我们将持续为您更新最新资讯!

查看全部

相关生活资讯推荐

  • 支付寶APP如何寫個福字
    1、首先打開【支付寶】APP軟件。2、然後點擊【寫個福字五福臨門】。3、然後選擇【福字字體】。4、然... 2023-07-08
  • 什麼牌子的帳篷最好野營帳篷什麼牌子好
    第一、首先,牧高笛的野營帳篷是比較好的,這個品牌的野營帳篷是比較受廣大消費者的喜愛的,主要是該品牌的野營帳篷的質量比較好,搭建也較為容易,非常的耐用。第二、其次,凱樂石的野營帳篷也是相當不錯的,這個品牌的野營帳篷的質量也是非常好的,而且外觀上看起來顯得特别的好看,在晚上的時候,其實是天冷的時候,保暖... 2023-07-08
  • 冬季防寒保暖小技巧
    1、冬季要泡腳,冬季的時候,腳部保暖措施一定要做到位,因為寒氣很容易通過腳部進入到我們體内,而這個時... 2023-07-08
  • 面試中如何回答自己的優缺點
    1、面試之前,先對自己各方面的優缺點做一個評估。這個評估可以是各方面的,比如學習、工作、興趣、思維、... 2023-07-08
  • 短道速滑有什麼技巧
    第一、短道速滑的時候身體蹲下的姿勢是很重要的,身體的中心要放到大腿上邊,在滑冰的過程中要用大腿來帶動小腿的力量。第二、身體傾斜度也是很重要的,在速滑的過程中,身體盡量都要保持在一個三點一線的狀态,身體要向左最大程度地傾斜至貼近地面。第三、速滑的時候雙腳蹬的動作也很重要,一定不能夠側跨來前進,這個動作... 2023-07-08

热门生活资讯推荐

  • 生活 藍黑白金裙子的事是啥原因啊
    1、藍黑白金裙子科學解釋是:人類的個體差異,對色彩的感知度不同。比如每個人不同程度的夜盲症,比如色盲... 2023-07-08
  • 生活 win10恢複出廠右鍵轉圈
    1、按Windows+R快捷鍵,開啟運行窗口。2、在運行頁面輸入Regedit,開啟注冊表編輯器。3... 2023-07-08
  • 生活 什麼是減數什麼是被減數
    一、被減數被減數是數學名詞,是指在減法算式中,減号前面的數是被減數,減号後面的數是減數,等号後面的數... 2023-07-08
  • 生活 龍江健康碼注冊不成功怎麼辦
    1、更換手機号,現在注冊都必須通過手機号驗證才可以申請注冊的,不可以直接申請注冊了。2、如果是驗證碼... 2023-07-08
  • 生活 大興國際機場占總面積多少
    1、北京大興國際機場占地面積約150平方公裡。2、大興國際機場總投資約800億元,将建設4條跑道、1... 2023-07-08
  • 生活 翻土最好的土方法
    1、先把盆底的孔用可以漏水的東西墊上,免得土随着水流出去了,你也可以根據自己身邊的材料看有什麼用什麼... 2023-07-08
  • 生活 怎麼做鴨棚
    1、場址選擇我們在搭建鴨棚之前,首先需要選好鴨棚的搭建地址。在規模養殖時,鴨棚的建設場址應選一個背風... 2023-07-08
  • 生活 win8的磁盤管理器在哪
    1、第一種打開方式:首先右鍵點擊“這台電腦”,然後選擇“管理(G)”選項。在彈出的窗口中依次點擊“存... 2023-07-08
  • 生活 打春有啥忌諱
    1、打春不看病,倘若看病就意味着一年都沒有好運氣。這個說法不過是想讨個好彩頭,就像大年初一不看病一樣... 2023-07-08
  • 生活 ip地址配置異常怎麼辦
    1、問題原因。在局域網中,電腦、手機等設備的IP地址都是由路由器自動分配的,當出現兩台或者兩台以上的... 2023-07-08

网友关注

  • 生活 淮山怎麼處理不癢
    1、水煮去皮法:(1)将鍋内倒入适量清水,開火,加熱至沸騰。(2)将山藥放入鍋中煮五分鐘,可輕松削皮... 2023-07-08
  • 生活 如何美白全身
    1、要達到皮膚的美白,主要是減少黑色素在表皮層的沉積。對于減少黑色素沉積的一些因素,比如說減少紫外光... 2023-07-08
  • 生活 考駕照要體檢嗎
    1、考駕照要體檢。2、身高:申請大型客車、牽引車、城市公交車、大型貨車、無軌電車準駕車型的,身高為1... 2023-07-08
  • 生活 一條魚的寓意和象征
    1、“魚”與“餘”諧音,所以魚象征着富貴。我國民俗歲末祭祖中講究供魚,取年年有餘魚之吉利,則是對魚的... 2023-07-08
  • 生活 海天盛宴是什麼
    1、海天盛宴是一場在海南三亞市舉辦的多方位高端生活方式展。這場一年一度的盛會持續四天,主要包括遊艇展... 2023-07-08
  • 生活 mw325r路由器怎麼設置的
    1、首先按照說明書将貓和電腦正确連接。2、線路連接好以後保證貓和路由器電源打開并正常使用了。然後打開... 2023-07-08
  • 生活 如何洗掉衣服上的木蠟油
    1、把沾有蠟油的衣服,平鋪在桌面上。2、把吸水性好的紙張,放在有蠟油的地方,紙張要4層或6層。3、在茶缸裡加上開水,放在已經墊好的紙張,約幾秒鐘即可将蠟油融化,并吸在紙張上面。 2023-07-08
  • 生活 地皮菜清洗絕招
    1、把新鮮地皮菜放在幹淨的清水中(如果是幹的地皮菜就提前泡軟),用手攪動,讓地皮菜和水一起旋轉5分鐘... 2023-07-08
  • 生活 鹹蛋黃燒蝦怎麼做
    1、準備好食材:大蝦300克,澱粉适量、食用油适量、蒜末适量,鹹蛋黃2個,蔥花适量。2、準備洗幹淨的大蝦300克,用刀開背去掉蝦線。加入50克澱粉,攪拌均勻。3、平底鍋倒上20克食用油,放上裹滿澱粉的蝦。4、小火煎至表面微焦,翻面煎一會,盛出備用。5、然後倒入10克蒜末,小火煸香。6、然後放入兩個鹹... 2023-07-08
  • 生活 菠蘿去除甲醛的方法
    1、菠蘿除甲醛那純屬扯,根本就是掩耳盜鈴,和說橘子皮、醋除甲醛是一樣的,一點小效果沒有,完全是靠氣味... 2023-07-08
  • 生活 微信黑名單怎麼解除
    1、要将好友拉出黑名單,需要在微信主頁面中找到“我”,然後點擊“設置”。2、在“設置”頁面點擊“隐私... 2023-07-08
  • 生活 羊毛衫怎麼洗不會縮水
    1、選用中性溫和的洗滌劑,以百分之三的比例與水混合,進行洗滌。2、控制好水溫,水溫不能太高,也不能是... 2023-07-08
  • 生活 樓頂扇怎麼安裝
    你好,一般樓頂扇安裝,首先你需要從主電源線拉三根線(火線.零線地線)到調速器接線盒,從接線盒出來三根... 2023-07-08
  • 生活 臘月二十七可以掃塵嗎
    1、掃塵日,即臘月二十四,所謂“掃塵”就是年終大掃除,家家戶戶清掃蛛網、揚塵、清洗。雖說“二十四,掃... 2023-07-08
  • 生活 買來的生海帶怎麼處理
    1、把新鮮海帶放入水中浸泡,水要沒過海帶把它全部浸泡在裡面,浸泡30分鐘以上,浸泡時可以撒入一些食用鹽,可以殺死表面微生物。2、将浸泡好的海帶撈出,平攤在菜闆上,用刷子進行依次刷洗,把表面的黏糊糊的物質刷洗幹淨,并用清水沖洗。3、把一塊海帶切成片裝或者絲狀,把一鍋開水燒開然後把海帶倒入鍋中煮沸,一邊煮一邊用筷子進行攪拌,等到海帶呈鮮綠色的時候關火撈出,把煮好的海帶用流動的清水再次沖洗即可。海帶:海 2023-07-08
  • 生活 怎麼辦社保卡
    1、一般進入企業或單位,都會給每位員工辦理社保,如果單位給你繳納了社保,單位會為你一并辦理社保卡,當... 2023-07-08
  • 生活 若蘭寺在哪裡?
    1、蘭若寺,其實是河南省扶溝縣蘭若寺。原名蘭若庵,位于河南省扶溝縣城東南十八裡焦橋村,賈魯河(原惠民... 2023-07-08
  • 生活 出馬仙是什麼意思
    1、出馬仙,原始宗教薩滿教的延續,修煉有成的精靈神怪出山為濟世渡人。在人群中選出自己的弟子,借弟子人... 2023-07-08
  • 生活 多肉開花了要剪掉嗎
    1、剪掉花。多肉開花後如果剪掉它,必然減少養分流失,花朵生長的話,肯定會吸收大量養分,緻使葉片遠遠不... 2023-07-08
  • 生活 微信運動裡面占領朋友的封面是什麼意思
    1、信運動裡面占領朋友的封面是在對方好友裡面看,如果當天的運動步數你是走的步數最多的話,就排行第一名... 2023-07-08
  • 生活 早春釣草魚方法
    1、首先盡管在早春的時候,天氣慢慢變得暖和了起來,水中的草魚也開始活躍起來,但是卻沒有完全恢複所有的... 2023-07-08
  • 生活 九裡香冬天怎麼養
    1、溫度。了解九裡香的習性之後,便能知道它适宜生長的溫度是20℃到32℃,冬季的話要注意它的保暖,一般冬季溫度在5℃時便能安全過冬,但如果低于0℃時,九裡香就有可能會被凍死,畢竟它耐寒性比較差。建議在冬季養殖時,最好将它置于室内,陽光比較充足的地方。2、澆水。九裡香還是可以适應幹一些的環境的,平時也... 2023-07-08
  • 生活 男生怎麼搭配衣服技巧
    男生想要變帥變有型,除了要搞定發型外,穿搭方面也不容忽視!别再怨天尤人說自己是個普男而放棄任何變帥的機會了,其實你隻要會一些穿搭小心機,照樣也能突顯你的男性魅力。1.微合身開扣的衣服對于男人來講,是否合身往往是選擇服裝的重要關鍵點之一。較合身的衣服會讓整體看起來更利落有精神,再加上胸前的開扣設計更會... 2023-07-08
  • 生活 夢見我的兒子名字代表什麼
    1、做生意的人夢見我的兒子名字,代表有财利,得祿。2、本命年的人夢見我的兒子名字,意味着不可三心兩意,心情不穩定,諸事無成,少外出。3、戀愛中的人夢見我的兒子名字,說明有誠信心對待婚姻可成。4、懷孕的人夢見我的兒子名字,預示生女,冬占生男,宜多保重,勿動胎氣。 2023-07-08
  • 生活 福壽祿三星擺在卧室裡可以嗎
    1、卧室主健康和夫妻和諧,所以把福祿壽擺放在卧室中,對于主人的健康運勢以及生育都會帶來一定幫助,畢竟在福祿壽三星之中,壽星主壽命、健康,所以這一點和卧室的風水氣運相符,而福星則是主福氣放在卧室中則是會給夫妻增添兒孫福,讓家中人丁興旺。所以把福祿壽三星請到卧室中還是比較合适的。2、卧室乃是家人休息睡覺... 2023-07-08
  • 生活 最佳驅鼠方法
    1、環境滅鼠:老鼠需要水、食物以及隐蔽的栖息條件才能生存和繁殖,因此創造一個不适宜其生存的環境就能使... 2023-07-08
  • 生活 旋葉姬星美人怎麼扡插
    1、葉姬星美人扡插之前先要剪下枝條,可從頂端剪下生長良好的枝條,莖葉部分要飽滿、充實,沒有病蟲害的影響,大約5-7厘米左右。2、配制準備好合适的基質,可用河沙、泥炭土配制,适當噴水維持好濕度,然後将剪下來的枝條插到基質之中,放在陰涼通風的地方,等待根部長出來。3、旋葉姬星美人喜歡幹燥、陽光充足的生長... 2023-07-08
  • 生活 怎樣做防塵風帽
    1、拿一張報紙,先對折一下。2、對折好後,再對折一下。3、展開開對折,沿着對折線折對角。4、折好對角... 2023-07-08
  • 生活 好看又好聽特霸氣網名
    1、别碰我,我有刺2、隻沾花不惹草3、麻煩關下月亮4、少年不再年少5、談情不如逗狗6、把傷心藏起來7... 2023-07-08
  • 生活 timing什麼意思
    1、timing指的是時機的意思,常見于網絡fps射擊遊戲當中。2、舉個例子就是你和對方對槍的時候,... 2023-07-08