c++ - this 指针和 QSharedPointer

标签 c++ qt qt5 shared-ptr qsharedpointer

我有一个类似树节点的类,名为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;
};

此类可以有一个父级和一组子级。我在实现 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_parentPtrparentPtr,从而thisPtr 引用计数减 1;这 3 个智能指针现在的引用计数为 3。
  6. 执行退出 Message::setParent 并销毁 parentPtr,将 m_parentPtrthisPtr 的引用计数减 1
  7. 执行返回到Message::addChild。现在 thisPtr 的引用计数为 2。

实际发生的情况:

当执行退出 Message::addChild 中的 if 语句时,thisPtr 引用计数再次减 1,留下 thisPtr 的引用计数为 1。这使得一切都中断,因为执行存在 Message::addChildthisPtr 被销毁,因此 this 被删除.

我的问题:

为什么当执行退出 Message::addChild 中的 if 语句时,thisPtr 引用计数再次减少,或者那里实际发生了什么? ..

以下是它在调试器中的运行方式: enter image description here

最佳答案

  1. As Message::setParent gets executed, m_parentPtr = parentPtr; will increase m_parentPtr, parentPtr and thus thisPtr reference counts by 1; these 3 smart pointers now have a reference count of 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成员(member)。

5.4。 5.1的临时共享指针被销毁,从而销毁了子进程。

更一般地说,您有一个循环引用: parent 拥有 child , child 拥有他们的 parent ,这是内存泄漏和删除后使用错误的根源。构造拥有其他共享指针已拥有的原始指针的新共享指针会导致双重删除和删除后使用错误;共享指针不会互相了解,它们的引用计数将独立变化。您应该调查 QWeakPointer 打破循环并 QEnableSharedFromThis 安全地获取指向 *this 的共享指针.

关于c++ - this 指针和 QSharedPointer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41837870/

相关文章:

c++ - 什么更快? (a+a 与 2*a 及更多)

c++ - 确保文件名不超出范围

c++ - 通过 Qt 播放 mov 文件

c++ - DLL 注入(inject)有效,除非我在 Qt Creator 中编译它

c++ - 无法将 Qml 信号连接到 C++ 插槽

c++ - 静态链接的应用程序是否也可以链接到一些动态库?

c++ - 迭代器或 reverse_iterator 的一个变量?

c++ - 在 C++ 中使用 ofstream 打开现有的 .doc 文件

c++ - 位域操作中的 operator[] 重载?

c++ - 与单数迭代器进行比较是非法的吗?