[英]this pointer and QSharedPointer
I have a tree-node like class called Message
which looks like this:我有一个类似 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;
};
This class can have a parent and a set of children.这个 class 可以有一个父母和一组孩子。 I have a problem when I implemented the
addChild
and setParent
member functions:我在实现
addChild
和setParent
成员函数时遇到问题:
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));
}
}
What I expect will happen:我期望会发生的事情:
Message::addChild
gets called Message::addChild
被调用thisPtr
gets created with a reference count of 1 thisPtr
创建时引用计数为 1childPtr->parent() != thisPtr
will be resolved to true
childPtr->parent() != thisPtr
将被解析为true
childPtr->setParent(thisPtr);
, Message::setParent
gets executed and thisPtr
reference count will increase by 1 as a copy of the shared pointer is created. Message::setParent
被执行并且thisPtr
引用计数将随着创建共享指针的副本而增加 1。 Now thisPtr
has a reference count of 2thisPtr
的引用计数为 2Message::setParent
gets executed, m_parentPtr = parentPtr;
Message::setParent
被执行时, m_parentPtr = parentPtr;
will increase m_parentPtr
, parentPtr
and thus thisPtr
reference counts by 1;m_parentPtr
、 parentPtr
和thisPtr
引用计数增加 1; these 3 smart pointers now have a reference count of 3.Message::setParent
and destroy parentPtr
decreasing the reference count of m_parentPtr
and thisPtr
by 1Message::setParent
并销毁parentPtr
将m_parentPtr
和thisPtr
的引用计数减 1Message::addChild
.Message::addChild
。 Now reference count of thisPtr
is 2.thisPtr
的引用计数是 2。 What actually happens:实际发生了什么:
When execution exits the if
statement in Message::addChild
thisPtr
reference count decreases again by 1, leaving thisPtr
with a reference count of 1. This makes everything break as when execution exists Message::addChild
, thisPtr
gets destroyed, thus this
deleted.当执行退出
Message::addChild
中的if
语句时, thisPtr
引用计数再次减少 1,使thisPtr
的引用计数为 1。这使得一切都中断,因为当执行存在Message::addChild
时, thisPtr
被销毁,因此this
被删除。
My question:我的问题:
Why does thisPtr
reference count decreases again by when execution exits the if
statement in Message::addChild
or what actually happens there?...为什么
thisPtr
引用计数会在执行退出Message::addChild
中的if
语句或那里实际发生的情况时再次减少?...
- As
Message::setParent
gets executed,m_parentPtr = parentPtr;
当
Message::setParent
被执行时,m_parentPtr = parentPtr;
will increasem_parentPtr
,parentPtr
and thusthisPtr
reference counts by 1;将增加
m_parentPtr
,parentPtr
,因此thisPtr
引用计数增加1; these 3 smart pointers now have a reference count of 3.这3个智能指针现在的引用计数为3。
5.1. 5.1。 Then,
setParent
constructs a temporary shared pointer to the child with reference count 1 and calls addChild
on the parent: 然后,
setParent
构造一个指向引用计数为1的子级的临时共享指针,并在父级上调用addChild
:
m_parentPtr->addChild(Message::Ptr(this));
5.2. 5.2。
addChild
creates a shared pointer to the parent with reference count 1 : addChild
创建一个指向引用计数为1的父级的共享指针:
Message::Ptr thisPtr(this);
5.3. 5.3。
addChild
returns, destroying that shared pointer of 5.2, which destroys the parent, which destroys the parent's QSet<Message::Ptr> m_children
member. addChild
返回,破坏了5.2的共享指针,破坏了父节点,这破坏了父节点的QSet<Message::Ptr> m_children
成员。
5.4. 5.4。 The temporary shared pointer of 5.1 is destroyed, which destroys the child.
5.1的临时共享指针被破坏,这将破坏子代。
More generally, you have a cyclic reference: parents own children, and children own their parents, which is a recipe for memory leaks and use-after-delete bugs. 一般来说,您有一个循环引用:父母拥有孩子,而孩子拥有父母,这是内存泄漏和删除后使用错误的秘诀。 Constructing new shared pointers owning raw pointers already owned by other shared pointers is a recipe for double-delete and use-after-delete bugs;
构造拥有其他共享指针已经拥有的原始指针的新共享指针是双重删除和使用后删除错误的诀窍。 the shared pointers won't know about each other, their reference counts will vary independently.
共享的指针不会相互了解,它们的引用计数将独立变化。 You should investigate
QWeakPointer
to break the cycle and QEnableSharedFromThis
to safely obtain a shared pointer to *this
. 您应该研究
QWeakPointer
来打破循环,并研究QEnableSharedFromThis
以安全地获取指向*this
的共享指针。
See The QEnableSharedFromThis in the Qt documentation.请参阅Qt文档中的 QEnableSharedFromThis。 This should solve your issue.
这应该可以解决您的问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.