Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 此指针和QSharedPointer_C++_Qt_Qt5_Shared Ptr_Qsharedpointer - Fatal编程技术网

C++ 此指针和QSharedPointer

C++ 此指针和QSharedPointer,c++,qt,qt5,shared-ptr,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 = Mess

我有一个类似树节点的类,名为
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;
};
我预期会发生什么:

  • Message::addChild
    被调用
  • thisPtr
    创建时引用计数为1
  • childPtr->parent()!=此PTR
    将解析为
    true
  • childPtr->setParent(thisPtr)
    Message::setParent
    将被执行,
    thisPtr
    引用计数将随着共享指针副本的创建而增加1。现在
    thisPtr
    的引用计数为2
  • 当执行
    Message::setParent
    时,
    m_parentPtr=parentPtr
    将增加
    m_parentPtr
    parentPtr
    ,从而
    thisPtr
    参考计数增加1;这3个智能指针现在的引用计数为3
  • 执行退出
    Message::setParent
    并销毁
    parentPtr
    m_parentPtr
    thisPtr的引用计数减少1
  • 执行返回到
    Message::addChild
    。现在,该PTR的参考计数为2
  • 实际发生的情况:

    当执行退出时,
    Message::addChild
    thisPtr
    中的
    if
    语句引用计数再次减少1,使
    thisPtr
    的引用计数保持为1。当执行存在时,
    Message::addChild
    thisPtr
    被销毁,因此
    This
    被删除

    我的问题:

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

    以下是它在调试器中的运行方式:

  • 当执行
    Message::setParent
    时,
    m_parentPtr=parentPtr
    将增加
    m_parentPtr
    parentPtr
    ,从而
    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 m_子级
    成员

    5.4。5.1的临时共享指针被销毁,这将销毁子级


    更一般地说,您有一个循环引用:父母拥有孩子,孩子拥有他们的父母,这是导致内存泄漏和删除bug后使用的一个处方。构建新的共享指针(拥有其他共享指针已经拥有的原始指针)是双重删除和删除错误后使用的方法;共享指针彼此不了解,它们的引用计数将独立变化。您应该进行调查,以打破这种循环,并安全地获得指向
    *此

    的共享指针。您不能将
    *此
    的所有权移交给
    QSharedPointer
    (您甚至多次这样做)。阅读。哇,这是一个令人讨厌的动画-难道你不能把它转换成文本形式吗?@JesperJuhl嗯,这正是我在这7点上所做的,我期待着会发生的事情…@molbdnilo是的,你是对的!哦,我忘了说“然后扔掉那个讨厌的周年纪念”;-)但也许那只是我。。
    Message::Ptr thisPtr(this);