tft每日頭條

 > 生活

 > c指針的作用

c指針的作用

生活 更新时间:2025-09-16 18:43:25

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-08
  • win10強制關閉飛行模式
    win10強制關閉飛行模式的具體步驟如下:1、首先點擊桌面左下方的導航圖标,在彈出的窗口中點擊設置圖... 2023-07-08
  • 自己裝修怎麼刮膩子
    第一、測量尺寸在開始施工前,首先應用卷尺來将要裝修的牆面的面積進行測量,如長寬分别是多少等,隻有在了解清楚具體面積後,才能确定膩子粉的具體用量,或者可以直接将尺寸告知給商家,讓他來幫助确定用量。第二、購買材料在進行完貨比三家的工作後,接下來要做的就是根據面積來購買合适的膩子粉了,注意一定要仔細的對比... 2023-07-08
  • 36d是什麼意思
    1、36d是胸罩尺寸。2、36D是指下胸圍80CM,上下胸圍差是17.5CM左右,一般用作标識女性胸... 2023-07-08
  • 詩經取名男孩
    1、哲成。名字出自詩經中的句子:“哲夫成城”。/《蕩之什·瞻卬》寓意:哲本義為聰明,有智慧,也指聰明... 2023-07-08

热门生活资讯推荐

  • 生活 薄荷移植種植方法
    1、移植種植薄荷,要先準備好疏松肥沃和排水性良好,然後剪薄荷植株從舊土中挖出來,再栽種到新土裡面去即... 2023-07-08
  • 生活 人參榕冬天怎麼養
    1、土壤。它的生命力十分旺盛,無論什麼地方或者是土質,它都可以成長得十分茁壯,它還可以依附在石頭上。如果是養在屋内的話,最好用河中的沙土來養護它,想要讓它的根長得遒勁,可以加入肥料,最好是磷鉀含量比較高的。2、溫度。它傾向有光,溫暖有水的氛圍,最好是18-33度的溫度,如果是嚴冬,不能比10度更低,... 2023-07-08
  • 生活 白色防曬衣去污漬小妙招
    1、首先可以先用洗衣液,稀釋攪拌均勻,然後放入白色防曬服,再把防曬服清洗幹淨。如果第一個辦法沒有改善... 2023-07-08
  • 生活 十二生肖适合養什麼植物旺财
    1、生肖鼠。旺财植物:金錢樹。生肖屬鼠的人很注重積蓄錢财,但他們理财意識不是很強,在投資方面過于謹慎... 2023-07-08
  • 生活 裝修開工有什麼講究
    1、開工時間要吉利:裝修開工時間要大吉大利,也就是說,動工那天要是吉日,而且開工之前有一個儀式,普遍... 2023-07-08
  • 生活 如何省電
    1、鼠标點擊桌面開始“菜單欄”,看到“控制面闆”,打開控制面闆。2、因為是讓電腦省電,我們要對電源進... 2023-07-08
  • 生活 火龍果怎麼保鮮保存
    1、如果在室内存放,要盡量的放在陰涼并且沒有光的地方。如果氣溫不太高,切開後放在陰涼沒有光的地方,一... 2023-07-08
  • 生活 聯通怎麼查行動軌迹
    1、需要打開手機上的“信息”功能。2、進入短信頁面後,點擊右上角的編輯新短信。3、先輸入“10010... 2023-07-08
  • 生活 電線并線方法
    1、首先在牆體預埋導線管,後向導線管中穿裝導線。穿裝導線時需先向導線管中穿入牽引線,牽引線多采用具有... 2023-07-08
  • 生活 戶塵螨和粉塵螨是什麼東西
    1、戶塵螨的體型是長圓形,又被稱為歐洲塵螨,是在歐亞大陸上最常見的緻敏性螨種。戶塵螨主要存在于一些紡... 2023-07-08

网友关注

  • 生活 如何計算BMI指數
    1、BMI的計算公式:體質指數(BMI)=體重(kg)÷身高^2(m)EX:70kg÷(1.75×1... 2023-07-08
  • 生活 自熱小火鍋的發熱包怎麼用
    1、首先取出醬包将鍋底擠入塑料碗内,接着依次加入菜包,往塑料碗中注入冷水至刻度線的位置。2、然後取出... 2023-07-08
  • 生活 愛馬仕是什麼
    1、愛馬仕Hermès)是世界著名的奢侈品品牌,1837年由ThierryHermès創立于法國巴黎,早年以制造高級馬具起家,迄今已有170多年的悠久曆史。2、愛馬仕是一家忠于傳統手工藝,不斷追求創新的國際化企業,截至2014年已擁有箱包、絲巾領帶、男、女裝和生活藝術品等十七類産品系列。愛馬仕的總店... 2023-07-08
  • 生活 qq清除的文件在哪可以找回
    1、qq文件删除了可以嘗試用數據恢複軟件來找回,需要借助其他恢複軟件.2、點擊進入誤删除文件,選中要... 2023-07-08
  • 生活 杜甫草堂在哪
    1、杜甫草堂地理位置:四川省成都市青羊區青華路38号。2、杜甫草堂,是中國唐代大詩人杜甫流寓成都時的... 2023-07-08
  • 生活 裝修的流程和步驟
    1、設計。自己動手裝修房子,首先要有一個設計方案。這個設計方案要根據自己的喜好、需求和經濟去制定且執... 2023-07-08
  • 生活 紅燒啤酒鵝怎麼做好吃竅門
    1、食材:鵝三分之二、啤酒三瓶、桂皮随意、冰糖随意、小紅椒随意、大蒜随意、生抽随意、老抽随意、鹽随意... 2023-07-08
  • 生活 手機充電插頭壞了該怎麼辦呢
    1、充電器的指示燈不亮,一般是插頭未接通電源。尤其是可活動插頭,極易接觸不良,我們首先将充電器用螺栓... 2023-07-08
  • 生活 女生送男生皮筋是什麼意思
    1、送皮筋最早來源于“男生帶皮筋”,“帶小皮筋的男生”主要是指這個男生有女朋友了。其最開始的意思主要... 2023-07-08
  • 生活 如何選擇合适的裝修公司
    第一、盡量選擇知名的公司選擇裝修公司就和我們挑選品牌産品一樣。品牌産品,具有一定的公信力,所以它的質量一般會有比較好的保證。知名公司的裝修工藝一般會有比較标準的規範,不會像市面上所見的遊擊隊一樣。所以選擇知名的公司,我們的業主也可以比較放心。第二、看營業執照一個正規公司都應該要有正規營業執照。我們挑... 2023-07-08
  • 生活 雞骨頭穿串技巧
    1、我們把肉切成盒子大小,平整的放入盒子的内部,接下來手握一把簽子順時間推過去,将簽子平穩地固定在卡... 2023-07-08
  • 生活 簡易呼吸器使用方法
    1、将簡易呼吸器連接好,調節氧氣流量,将儲氧袋中充滿氧氣。2、使患者仰卧,放平,操作者站于患者頭頂後... 2023-07-08
  • 生活 如何修改家裡的wifi密碼
    1、确定【電腦】與【無線路器】已聯通,在電腦打開【浏覽器】,在浏覽器地址欄裡輸入路由器IP地址【19... 2023-07-08
  • 生活 跨省如何注銷手機号碼
    1、目前隻支持本省範圍内異地号碼注銷,跨省的話是不支持的。2、如果是深圳卡可以在廣州辦注銷,去當地官... 2023-07-08
  • 生活 廚房收納整理小技巧
    1、小廚具。把炒菜的廚具懸挂到一塊,碗筷等餐具放在消毒櫃/洗碗櫃裡,使用頻率低的小廚具可以找一個比較... 2023-07-08
  • 生活 天竹修剪方法
    1、短截。冬末春初之際,根據預期的設計效果,在坯樁上選取高度适中的潛伏芽點短截。首年任其自由生長,第... 2023-07-08
  • 生活 贊美幹花的簡短句子
    1、人們看慣了花落花開,春去秋來,卻又感歎美麗時常短暫,幸福總是刹那。2、無意間,看見了陽台角落裡的... 2023-07-08
  • 生活 水銀溫度計腋下測量需要幾分鐘
    1、腋下測溫方法,解開衣服,先用幹毛巾擦去腋下的汗水,将水銀端放于腋窩的頂部,水銀端不能伸出腋窩外,... 2023-07-08
  • 生活 羽絨服能洗衣機洗嗎
    1、洗羽絨服可以用洗衣機洗。但是最好不要甩幹,一些質量不好,不合格的衣服,會在甩幹的時候爆炸。2、最... 2023-07-08
  • 生活 鮮白術價格多少錢一斤
    1、目前白術一斤價格在12元左右。2、白術:菊科蒼術屬多年生草本植物,高可達60厘米,結節狀根狀莖。... 2023-07-08
  • 生活 菜心怎麼保存才能保鮮
    1、采收和分級菜心收獲的标準一般是以菜薹的高度和薹葉的先端齊平,初現花蕾俗稱“齊口花”為适期,這時質... 2023-07-08
  • 生活 oppor17微信附近人怎麼看不到我
    1、微信附近的人找不到自己一般是因為使用微信查找附近的人後,會确定手機的地理位置信息,此地理位置信息... 2023-07-08
  • 生活 工業三廢是指哪三個
    1、工業三廢是指工業生産過程中排出的廢氣、廢水、廢渣的簡稱。2、工業廢氣是指工業生産過程中排放出的各... 2023-07-08
  • 生活 屋裡适合養什麼花最好
    1、富貴竹,富貴竹又稱“萬年竹”、“萬年青”,是廣受歡迎的“搖錢樹”,在家裡養富貴竹象征招财。2、水... 2023-07-08
  • 生活 192.168.124.1手機登陸w...
    先要将手機連接無線路由器的無線網絡,浏覽器地址欄輸入路由器網關地址192.168.124.1。然後依... 2023-07-08
  • 生活 煙灰缸裡不放水是什麼意思
    1、窮困潦倒煙灰缸裡不放水是一個人非常窮困潦倒的意思,是男生之間互相開玩笑的話語,在沒有錢買煙時候,... 2023-07-08
  • 生活 空調制熱沒反應不出風制冷好使
    1、空調已經老化:在一般的情況下的話,空調的使用壽命在八年,十年,十五年的樣子,為什麼這樣說呢,因為... 2023-07-08
  • 生活 長江全面禁捕10年可以釣魚嗎
    1、長江禁漁期是不可以釣魚的,禁漁期内如果偷釣可能會面臨罰款。2、長江禁漁令生效後,江面上的“正規”... 2023-07-08
  • 生活 消除床上靜電的最簡單方法
    1、在卧室盡量不要放置電視機,因為電視劇本身帶有電,這樣的話卧室的被子更容易産生靜電。2、盡量不選擇... 2023-07-08
  • 生活 多肉扡插方法
    1、扡插多肉植物可使用飽滿的葉片,從母株上面将葉片掰下,但不能将它的生長點破壞掉。準備好幹淨的介質,... 2023-07-08