日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

【C++】智能指针 Smart Pointer

發布時間:2024/9/15 c/c++ 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【C++】智能指针 Smart Pointer 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

智能指針

      • 智能指針 Smart Pointer
        • auto_ptr
        • 智能指針的自實現
        • shared_ptr
          • weak_ptr
        • unique_ptr

智能指針 Smart Pointer

用來改善傳統指針的問題

  • 需要手動管理內存

  • 容易發生內存泄露(忘記釋放、出現異常等)

    比如:

    一旦test()拋出異常,p指針的內存就不會被釋放,發生內存泄露。

  • 釋放后產生野指針

  • 智能指針就是為了解決傳統指針存在的問題

    • auto_prt:屬于C++98標準,在C++11已不推薦使用(有缺陷,比如不能用于數組
    • shared_ptr:屬于C++11標準
    • unique_ptr:屬于C++11標準

    auto_ptr

    class Person {int m_age; public:Person() {cout << "Person()" << endl;}Person(int age): m_age(age) {cout << "Person(int)" << endl;}~Person() {cout << "~Person()" << endl;}void run() {cout << "run()" << endl;} };void test() {// 可以理解為:智能指針p指向了堆空間的Person對象auto_ptr<Person> p(new Person(20));p->run(); }int main() {test();getchar();return 0; }// 輸出: // Person(int) // run() // ~Person() // 并沒有調用析構函數,但會自動調用

    智能指針不能指向棧空間的對象!因為智能指針是堆空間指針,析構時會double free!

    {Person person(20); // 創建在棧空間auto_ptr<Person> p(&person); // 堆空間指針指向棧空間對象p->run();// 會調用兩次析構函數 }

    不能作用于數組

    {auto_ptr<Person> p(new Person[10]); // 一個數組,里面有10個Person對象p->run(); } // 構造函數會調用10次,但析構函數只會調用一次,然后拋出異常

    可以使用shared_ptr

    智能指針的自實現

    template <typename T> class SmartPointer { private:T *m_obj; public:SmartPointer(T *obj): m_obj(obj) {}~SmartPointer() {if (m_obj == nullptr) return;delete m_obj;}T *operator->() { // 為了可以使用T類的成員函數return m_obj;} }; int main() {{SmartPointer<Person> p(new Person(20));p->run();// 看似是一個指針,實則是一個對象,重載了運算符}getchar();return 0; }

    shared_ptr

    • 多個shared_ptr可以指向同一個對象,當最后一個shared_ptr在作用于范圍內結束時,對象才會被自動釋放

      {shared_ptr<Person> p1(new Person(10));shared_ptr<Person> p2 = p1;shared_ptr<Person> p3 = p2;shared_ptr<Person> p4(p3); // 本質上都是p1// 當最后一個指針(p4)結束后,p1才會被自動釋放 }
      • 可以通過一個已存在的智能指針初始化一個新的智能指針

        shared_ptr<Person> p1(new Person()); shared_ptr<Person> p2(p1);
      • 針對數組的用法

        shared_ptr<Person> ptr1(new Person[5]{}, [](Person *p) { delete[] p;}); // 傳入lambda表達式表明想要怎么析構
    • shared_ptr的原理

      • 一個shared_ptr會對一個對象產生強引用

      • 每個對象都有個與之對應的強引用計數,記錄著當前對象被多少個shared_ptr強引用著

        • 可以通過shared_ptr的use_count函數獲得強引用計數
        {shared_ptr<Person> p1(new Person(10));cout << p1.use_count() << endl;shared_ptr<Person> p2 = p1;cout << p1.use_count() << endl;shared_ptr<Person> p3 = p2;cout << p1.use_count() << endl;shared_ptr<Person> p4(p3); cout << p1.use_count() << endl; } // 打印1 2 3 4
        • 當有一個新的shared_ptr指向對象時,對象的強引用計數就會+1
        • 當有一個shared_ptr銷毀時,比如作用域結束,對象的強引用計數就會-1
        • 當一個對象的強引用計數為0時(沒有任何shared_ptr指向對象時),對象就會自動銷毀(析構
    • 循環引用

      你強引用我,我強引用你,大家都別銷毀

      class Person;class Car { public:shared_ptr<Person> m_person;~Car() {cout << "~Car()" << endl;} };class Person { public:shared_ptr<Person> m_car;~Person() {cout << "~Person()" << endl;} };int main() {{shared_ptr<Person> person(new Person());shared_ptr<Car> car(new Car());person->m_car = car;car->m_person = person;// 不會析構,會造成內存泄漏}getchar();return 0; }

    Person和Car的強引用計數都是2

    一旦main函數內的大括號結束,棧空間的person 和car的強引用結束,但堆空間的person和car相互的強引用并不結束

    所以Person和Car的強引用計數變為1,無法銷毀

    如何解決呢?

    使用弱引用(weak_ptr)

    weak_ptr
    • 會對一個對象產生弱引用

    • 可以指向對象解決shared_ptr的循環引用問題

      class Person;class Car { public:weak_ptr<Person> m_person;~Car() {cout << "~Car()" << endl;} };class Person { public:shared_ptr<Person> m_car;~Person() {cout << "~Person()" << endl;} };int main() {{shared_ptr<Person> person(new Person());shared_ptr<Car> car(new Car());person->m_car = car;car->m_person = person;// 不會析構,會造成內存泄漏}getchar();return 0; }

    當棧空間的Person和Car被銷毀后,Person先銷毀,因為Person強引用計數為0

    Person被銷毀后,Car的強引用也為0了,所以Car也會被銷毀

    unique_ptr

    unique_ptr也會對一個對象產生強引用,它可以確保同一時間只有1個指針指向對象

    int main() {{unique_ptr<Person> p1(new Person());unique_ptr<Person> p2(p1); // 報錯,不能把兩個指針指向同一個對象![在這里插入圖片描述](https://img-blog.csdnimg.cn/836d4fe420e64b24907529945889fda4.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASGFsbHVjaW5hdGlvbg==,size_20,color_FFFFFF,t_70,g_se,x_16)}getchar();return 0; }
    • 當unique_ptr銷毀時(作用域結束時),其指向的對象也就自動銷毀了
    • 可以使用std::move函數轉移unique_ptr的所有權
    int main() {unique_ptr<Person> p0;{unique_ptr<Person> p1(new Person());p0 = std::move(p1);}// 將p1的指向權轉移給p0// 所以當大括號結束后p0指向的對象不銷毀,因為p0的作用域getchar();return 0; } 與50位技術專家面對面20年技術見證,附贈技術全景圖

    總結

    以上是生活随笔為你收集整理的【C++】智能指针 Smart Pointer的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。