簡體   English   中英

這個指針和 QSharedPointer

[英]this pointer and QSharedPointer

我有一個類似 class 的樹節點,名為Message ,如下所示:

class Message
{
public:
    using Ptr = QSharedPointer<Message>;

public:
    explicit Message();
    explicit Message(Message::Ptr parentPtr);
    explicit Message(const Data &data, Message::Ptr parentPtr = Message::Ptr());

    void setParent(Message::Ptr parentPtr);
    Message::Ptr parent() const;
    bool hasParent() const;

    QSet<Message::Ptr> children() const;
    void setChildren(const QSet<Message::Ptr> &children);
    bool hasChildren() const;

    Data data() const;
    void setData(const Data &data);

private:
    void addChild(Message::Ptr childPtr);
    void removeChild(Message::Ptr childPtr);

private:
    Message::Ptr m_parentPtr;
    QSet<Message::Ptr> m_children;
    Data m_data;
};

這個 class 可以有一個父母和一組孩子。 我在實現addChildsetParent成員函數時遇到問題:

void Message::addChild(Message::Ptr childPtr)
{
    if (!m_children.contains(childPtr)) {
        m_children.insert(childPtr);
    }

    Message::Ptr thisPtr(this);

    if (childPtr->parent() != thisPtr) {
        childPtr->setParent(thisPtr);
    }
}

void Message::setParent(Message::Ptr parentPtr)
{
    if (m_parentPtr != parentPtr) {
        m_parentPtr = parentPtr;

        m_parentPtr->addChild(Message::Ptr(this));
    }
}

我期望會發生的事情:

  1. Message::addChild被調用
  2. thisPtr創建時引用計數為 1
  3. childPtr->parent() != thisPtr將被解析為true
  4. childPtr->setParent(thisPtr); , Message::setParent被執行並且thisPtr引用計數將隨着創建共享指針的副本而增加 1。 現在thisPtr的引用計數為 2
  5. Message::setParent被執行時, m_parentPtr = parentPtr; 會將m_parentPtrparentPtrthisPtr引用計數增加 1; 這 3 個智能指針現在的引用計數為 3。
  6. 執行退出Message::setParent並銷毀parentPtrm_parentPtrthisPtr的引用計數減 1
  7. 執行返回到Message::addChild 現在thisPtr的引用計數是 2。

實際發生了什么:

當執行退出Message::addChild中的if語句時, thisPtr引用計數再次減少 1,使thisPtr的引用計數為 1。這使得一切都中斷,因為當執行存在Message::addChild時, thisPtr被銷毀,因此this被刪除。

我的問題:

為什么thisPtr引用計數會在執行退出Message::addChild中的if語句或那里實際發生的情況時再次減少?...

以下是它在調試器中的運行方式: 在此處輸入圖像描述

  1. Message::setParent被執行時, m_parentPtr = parentPtr; 將增加m_parentPtrparentPtr ,因此thisPtr引用計數增加1; 這3個智能指針現在的引用計數為3。

5.1。 然后, setParent構造一個指向引用計數為1的子級的臨時共享指針,並在父級上調用addChild

m_parentPtr->addChild(Message::Ptr(this));

5.2。 addChild創建一個指向引用計數為1的父級的共享指針:

Message::Ptr thisPtr(this);

5.3。 addChild返回,破壞了5.2的共享指針,破壞了父節點,這破壞了父節點的QSet<Message::Ptr> m_children成員。

5.4。 5.1的臨時共享指針被破壞,這將破壞子代。

一般來說,您有一個循環引用:父母擁有孩子,而孩子擁有父母,這是內存泄漏和刪除后使用錯誤的秘訣。 構造擁有其他共享指針已經擁有的原始指針的新共享指針是雙重刪除和使用后刪除錯誤的訣竅。 共享的指針不會相互了解,它們的引用計數將獨立變化。 您應該研究QWeakPointer來打破循環,並研究QEnableSharedFromThis以安全地獲取指向*this的共享指針。

請參閱Qt文檔中的 QEnableSharedFromThis。 這應該可以解決您的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM