<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Qt雜談8.淺談Qt智能指針那些事

      1 引言

      在 Qt 中,智能指針是一種能夠自動管理對象生命周期的指針類型。通過使用智能指針,可以避免手動釋放內存和處理懸掛指針等常見的內存管理問題。Qt中常用的智能指針主要有以下幾種:

      • QPointer:QPointer 是 Qt 提供的空安全的智能指針,用于解決對象懸掛指針的問題。QPointer 在對象被刪除后會被自動設置為 nullptr,避免訪問已經無效的對象。它類似于普通指針,但提供了一些安全檢查。
      • QScopedPointer:QScopedPointer 是 Qt 提供的獨占所有權的智能指針,用于管理動態分配的對象。QScopedPointer 在超出作用域時自動刪除對象,確保對象在不再需要時被正確釋放。它不能被復制,因此每次只有一個擁有對象的QScopedPointer。
      • QSharedPointer:QSharedPointer 是 Qt 提供的共享引用計數的智能指針,可用于管理動態分配的對象。它通過引用計數跟蹤對象的引用次數,當引用計數歸零時會自動刪除對象。可以通過多個 QSharedPointer 共享同一個對象,對象只會在最后一個引用者釋放它時才會被刪除。
      • QWeakPointer:QWeakPointer 是 Qt 提供的弱引用智能指針,用于解決循環引用問題。QWeakPointer 可以引用由 QSharedPointer 管理的對象,但不會增加引用計數。QWeakPointer 需要轉換成 QSharedPointer 才能訪問對象,當引用計數為零時,訪問會失敗。

      2 案例分析

      2.1 QPointer

      QPointer 是 Qt 框架提供的一種智能指針,用于安全地處理對象的生命周期,并在對象銷毀后將指針置空,防止懸垂指針的問題。

      QPointer 主要用于在持有對象的弱引用的同時能夠檢測對象是否已被銷毀。通過 QPointer,即使持有一個對象的指針,也可以確保在對象被刪除后,該指針會被自動置空。這樣,在使用 QPointer 指針時,可以檢查指針是否有效來判斷對象是否存在。

      下面是一個示例,演示 QPointer 的用法:

      #include <QCoreApplication>
      #include <QPointer>
      #include <QDebug>
      
      class MyClass : public QObject
      {
          Q_OBJECT
      public:
          MyClass(const QString& name) : m_name(name)
          {
              qDebug() << "MyClass 構造函數,名稱為" << m_name;
          }
      
          ~MyClass()
          {
              qDebug() << "MyClass 析構函數,名稱為" << m_name;
          }
      
          QString getName() const { return m_name; }
      
      private:
          QString m_name;
      };
      
      int main(int argc, char *argv[])
      {
          QCoreApplication a(argc, argv);
      
          MyClass *obj = new MyClass("Object");
      
          QPointer<MyClass> myObject(obj);  // 創建一個 QPointer 對象來監視 MyClass 對象
      
          if (myObject) {
              qDebug() << "對象存在,名稱為" << myObject->getName();
          } else {
              qDebug() << "對象不存在";
          }
      
          delete obj;  // 銷毀對象,導致myObject為空
      
          if (myObject) {
              qDebug() << "對象存在,名稱為" << myObject->getName();
          } else {
              qDebug() << "對象不存在";
          }
      
          return a.exec();
      }
      

      結果輸出:

      MyClass 構造函數,名稱為 Object
      對象存在,名稱為 Object
      MyClass 析構函數,名稱為 Object
      對象不存在
      

      可以看出,通過使用 QPointer,即使持有對象的指針,也能夠安全地檢測對象是否有效。一旦對象被銷毀,QPointer 會自動將指針置空,避免了懸垂指針的問題,這樣可以在使用指向對象的指針時,更加安全和可靠。

      2.2 QScopedPointer

      使用 QScopedPointer 管理動態分配的內存時,它會確保在包含該 QScopedPointer 的作用域結束時,所管理的對象會被自動釋放,從而避免內存泄漏的問題。下面是一個示例:

      #include <QScopedPointer>
      #include <QDebug>
      
      class Resource {
      public:
          Resource() { qDebug() << "Resource 構造函數"; }
          ~Resource() { qDebug() << "Resource 析構函數"; }
      };
      
      void useResource()
      {
          QScopedPointer<Resource> scopedResource(new Resource());
      
          // 執行一些操作,使用資源
          qDebug() << "使用資源...";
      }
      
      int main()
      {
          useResource();
          qDebug() << "useResource 函數執行完畢";
      
          return 0;
      }
      

      如上,創建了一個名為 Resource 的類,并使用 QScopedPointer 在 useResource 函數內創建動態分配的 Resource 對象。當 useResource 函數結束時,QScopedPointer 的析構函數會被調用,并自動釋放所管理的 Resource 對象。

      輸出結果如下:

      Resource 構造函數
      使用資源...
      Resource 析構函數
      useResource 函數執行完畢
      

      從結果可以看出,Resource 的構造函數在 QScopedPointer 創建對象時被調用,而析構函數在 useResource 函數結束后被調用。這表明 QScopedPointer 在適當的時候自動釋放了對象的內存,確保沒有內存泄漏的問題。

      2.3 QSharedPointer和QWeakPointer

      2.3.1 QSharedPointer

      特點:

      • 用于管理動態分配的對象的所有權和生命周期。
      • 當存在至少一個 QSharedPointer 指向對象時,對象的內存不會被釋放。
      • 當最后一個指向對象的 QSharedPointer 超出作用域時,對象的內存會被釋放。
      • 可通過復制 QSharedPointer 來增加對象的引用計數,確保對象在合適的時候被釋放。

      下面舉個例子:

      #include <QSharedPointer>
      #include <QDebug>
      
      class MyClass
      {
      public:
          MyClass(int value) : m_value(value)
          {
              qDebug() << "MyClass 構造函數,數值為" << m_value;
          }
      
          ~MyClass()
          {
              qDebug() << "MyClass 析構函數,數值為" << m_value;
          }
      
          void setValue(int value)
          {
              m_value = value;
          }
      
          int getValue() const
          {
              return m_value;
          }
      
      private:
          int m_value;
      };
      
      int main()
      {
          QSharedPointer<MyClass> pointer1(new MyClass(10)); // 創建一個 QSharedPointer 智能指針,用于管理 MyClass 對象
      
          {
              QSharedPointer<MyClass> pointer2 = pointer1; // 復制構造函數,增加了 MyClass 對象的引用計數
      
              qDebug() << "pointer1 的值為" << pointer1->getValue();
              qDebug() << "pointer2 的值為" << pointer2->getValue();
      
              pointer2->setValue(20); // 通過 pointer2 修改對象的值
      
              qDebug() << "pointer1 的值為" << pointer1->getValue();
              qDebug() << "pointer2 的值為" << pointer2->getValue();
          } // pointer2 超出作用域,減少了 MyClass 對象的引用計數
      
          qDebug() << "pointer1 的值為" << pointer1->getValue();
      
          return 0;
      }
      

      結果輸出:

      MyClass 構造函數,數值為 10
      pointer1 的值為 10
      pointer2 的值為 10
      pointer1 的值為 20
      pointer2 的值為 20
      pointer1 的值為 20
      MyClass 析構函數,數值為 20
      

      如上,在 main 函數中,創建了一個 QSharedPointer 智能指針 pointer1,它指向一個值為 10 的 MyClass 對象。然后,通過復制構造函數創建了另一個指針 pointer2,指向同一個 MyClass 對象。這個操作導致 MyClass 對象的引用計數加一。

      在 pointer2 的作用域內,修改了 MyClass 對象的值,并觀察到修改同時影響了 pointer1 和 pointer2 指向的對象。當 pointer2 超出作用域時,MyClass 對象的引用計數減一,但不會立即銷毀,因為 pointer1 仍然持有它的引用。最后,當 pointer1 超出作用域時,MyClass 對象被正確地銷毀。

      2.3.2 QWeakPointer

      特點:

      • 用于解決 QSharedPointer 可能導致的循環引用問題。
      • 不會增加對象的引用計數,不影響對象的生命周期。
      • 可以從 QSharedPointer 或者另一個 QWeakPointer 創建,用于在需要時保持對對象的非擁有者式引用。
      • 如果關聯的 QSharedPointer 被釋放,QWeakPointer 會自動置空,避免懸空指針問題。

      這里重點說下循環引用,當兩個或多個對象彼此持有對方的強引用時,就會形成循環引用。這種情況下,對象無法被正常釋放,會導致內存泄漏。Qt 的 QWeakPointer 類是為了解決這個問題而引入的。

      QWeakPointer 允許創建一個弱引用指向被QSharedPointer管理的對象,但不會增加該對象的引用計數。弱引用不會阻止對象的銷毀,即使所有強引用都失效,對象的析構函數也能被正確調用。

      下面是一個循環引用的示例:

      #include <QSharedPointer>
      #include <QWeakPointer>
      #include <QDebug>
      
      class ObjectB;
      
      class ObjectA
      {
      public:
          ObjectA(const QString& name) : m_name(name) {}
      
          ~ObjectA()
          {
              qDebug() << "ObjectA 析構函數,名稱為" << m_name;
          }
      
          void setObjectB(const QSharedPointer<ObjectB>& objectB)
          {
              m_objectB = objectB;
          }
      
      private:
          QString m_name;
          QSharedPointer<ObjectB> m_objectB;
      };
      
      class ObjectB
      {
      public:
          ObjectB(const QString& name) : m_name(name) {}
      
          ~ObjectB()
          {
              qDebug() << "ObjectB 析構函數,名稱為" << m_name;
          }
      
          void setObjectA(const QSharedPointer<ObjectA>& objectA)
          {
              m_objectA = objectA;
          }
      
      private:
          QString m_name;
          QSharedPointer<ObjectA> m_objectA;
      };
      
      int main()
      {
          QSharedPointer<ObjectA> objectA(new ObjectA("ObjectA"));
          QSharedPointer<ObjectB> objectB(new ObjectB("ObjectB"));
      
          objectA->setObjectB(objectB);
          objectB->setObjectA(objectA);
      
          qDebug() << "程序結束";
      
          return 0;
      }
      

      結果輸出:

      程序結束
      

      如上,在 main 函數中,創建了兩個 QSharedPointer,用于管理 ObjectA 和 ObjectB 對象的生命周期。然后,通過 setObjectB 和 setObjectA 函數,相互設置對方的強引用,這樣就形成了循環引用,導致對象無法正常銷毀,從而出現內存泄漏。

      為了避免這個問題,將 m_objectB 和 m_objectA 至少一個聲明為 QWeakPointer 類型,如下:

      QSharedPointer<ObjectB> m_objectB -> QWeakPointer<ObjectB> m_objectB 
      或
      QSharedPointer<ObjectA> m_objectA -> QWeakPointer<ObjectA> m_objectA 
      

      由于使用了 QWeakPointer,不會增加對象的引用計數,這樣也就打破了循環引用。當 objectA 和 objectB 超出作用域時,它們的引用計數會遞減,對象能夠被正常銷毀。修改后結果輸出如下:

      程序結束
      ObjectB 析構函數,名稱為 "ObjectB"
      ObjectA 析構函數,名稱為 "ObjectA"
      

      可以看到,對象的析構函數被正確調用,大家可以自行驗證下。

      3 總結

      Qt 框架提供了多種智能指針類,用于簡化對象生命周期管理和避免懸垂指針問題,使用這些智能指針類可以更方便、安全地管理對象的生命周期,減少內存泄漏和懸垂指針問題的發生,提高代碼的可靠性和性能。

      posted @ 2023-12-29 17:19  Qt小羅  閱讀(2205)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 日韩中文日韩中文字幕亚| 亚洲综合一区无码精品| 国产一区在线播放av| 么公的好大好硬好深好爽视频| 欧美激欧美啪啪片| 亚洲av激情久久精品人| 亚洲精品国产自在久久| 色综合天天综合网中文伊| 亚洲一区二区偷拍精品| 韩产日产国产欧产| 成人亚欧欧美激情在线观看| 国产美女被遭强高潮免费一视频| 亚洲AV无码破坏版在线观看| 国产精品第一二三区久久| 漂亮的保姆hd完整版免费韩国| 国产精品国产精品偷麻豆| 国产中文字幕精品视频| 国内精品久久久久精免费| 亚洲区一区二区激情文学| 国产一区二区高清不卡| 日本阿v片在线播放免费| 在线成人| 久久夜色精品国产亚洲a| 日本高清中文字幕一区二区三区| 色婷婷综合久久久久中文一区二区| 又大又粗欧美成人网站| 日韩精品人妻av一区二区三区| 最新亚洲春色av无码专区| 视频一区视频二区中文字幕| 亚洲av在线观看| 亚洲成年av天堂动漫网站| 亚洲一区二区中文字幕| 屁屁影院ccyy备用地址| 老色鬼永久精品网站| 中文字幕一区二区三区麻豆| 尤物视频色版在线观看| 昌邑市| caoporn免费视频公开| 色 亚洲 日韩 国产 综合| 丰满人妻被黑人猛烈进入| 日韩丝袜欧美人妻制服|