Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.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++ 使用共享\u ptr和弱\u ptr时避免间接循环引用_C++_Boost_Shared Ptr_Cyclic_Weak Ptr - Fatal编程技术网

C++ 使用共享\u ptr和弱\u ptr时避免间接循环引用

C++ 使用共享\u ptr和弱\u ptr时避免间接循环引用,c++,boost,shared-ptr,cyclic,weak-ptr,C++,Boost,Shared Ptr,Cyclic,Weak Ptr,我目前正在组装一个严重依赖于的应用程序,到目前为止一切看起来都很好-我已经完成了我的工作,并且对使用shared\u ptrs的一些陷阱有了很好的了解 shared_ptr最常见的问题之一是循环依赖性-这些问题可以通过存储不影响链上对象生命周期的弱_ptr来解决。然而,我正努力让自己的头脑清醒过来,在需要通过弱\u ptr-存储指向外部对象的指针的时候,我不确定它是被禁止的、被阻止的还是安全的 下图描述了我的意思(黑色箭头表示shared_ptr;虚线表示弱_ptr): 父级包含两个子级的共

我目前正在组装一个严重依赖于的应用程序,到目前为止一切看起来都很好-我已经完成了我的工作,并且对使用
shared\u ptr
s的一些陷阱有了很好的了解

shared_ptr
最常见的问题之一是循环依赖性-这些问题可以通过存储不影响链上对象生命周期的
弱_ptr
来解决。然而,我正努力让自己的头脑清醒过来,在需要通过
弱\u ptr
-存储指向外部对象的指针的时候,我不确定它是被禁止的、被阻止的还是安全的

下图描述了我的意思(黑色箭头表示
shared_ptr
;虚线表示
弱_ptr
):

  • 父级包含两个子级的
    共享\u ptr
    s,这两个子级都使用
    弱\u ptr
    指向父级
  • 在第一个子级的构造函数中,我通过父级
    弱\ptr
    检索指向第二个子级的指针,并将其存储在本地
代码如下所示:

#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/enable_shared_from_this.hpp>

class child;
class child2;
class parent;

class parent : public boost::enable_shared_from_this<parent>
{
public:
    void createChildren()
    {
        _child2 = boost::make_shared<child2>(shared_from_this());
        _child = boost::make_shared<child>(shared_from_this());
    }

    boost::shared_ptr<child> _child;
    boost::shared_ptr<child2> _child2;
};

class child
{
public:
    child(boost::weak_ptr<parent> p)
    {
        _parent = p;
        _child2 = boost::shared_ptr<parent>(p)->_child2; // is this safe?
    }

    boost::weak_ptr<parent> _parent;
    boost::shared_ptr<child2> _child2;
};

class child2
{
public:
    child2(boost::weak_ptr<parent> p)
    {
        this->_parent = p;
    }

    boost::weak_ptr<parent> _parent;
};

int main()
{
    boost::shared_ptr<parent> master(boost::make_shared<parent>());
    master->createChildren();
}
#包括
#包括
#包括
#包括
班级儿童;
儿童2类;
班级家长;
类父级:public boost::从\u中启用\u共享\u
{
公众:
void createChildren()
{
_child2=boost::使_共享(从_this()共享_);
_child=boost::使_共享(从_this()共享_);
}
boost::共享的ptr孩子;
boost::共享\u ptr\u child2;
};
班童
{
公众:
子级(增强::弱ptr p)
{
_父母=p;
_child2=boost::shared\u ptr(p)->\u child2;//这样安全吗?
}
boost::弱ptr父级;
boost::共享\u ptr\u child2;
};
儿童2班
{
公众:
child2(boost::弱ptr p)
{
这个->\u父项=p;
}
boost::弱ptr父级;
};
int main()
{
boost::shared_ptr master(boost::make_shared());
master->createChildren();
}

我已经测试过了,它似乎工作正常(我没有收到任何内存泄漏的报告),但是我的问题是:这安全吗?如果没有,为什么不呢?

如果“p”已经(不知何故)被破坏了,你会得到坏的\u弱\u ptr异常。
因此,子构造函数期望异常是安全的,否则就不安全了。

子构造函数在您调用它时看起来是安全的。然而,总的来说它并不安全

该问题是由于在子构造函数中传递弱_ptr作为参数引起的。这意味着您需要担心弱指针是否用于不再存在的对象。通过在存储时将此参数更改为共享_ptr并转换为弱_ptr,我们知道该对象仍然存在。这是零钱:

child(boost::shared_ptr<parent> p)
{
    _parent = p;
    _child2 = p->_child2; // This is this safe
}
child(boost::shared_ptr p)
{
_父母=p;
_child2=p->\u child2;//这是保险箱
}
共享\u ptr最常见的问题之一是循环依赖性-这些问题可以通过存储不影响链上对象生命周期的弱\u ptr来解决

此循环依赖项存在或不存在。

如果问题存在,那么弱引用就不是一个选项

需要通过弱ptr存储指向外部对象的指针的位置

几乎不需要弱ptr


很少有非常特殊的情况下
弱ptr
是合适的,但大多数情况下它是
共享ptr
邪教的一部分:他们不是在出现问题时随机抛出
共享ptr
,而是随机抛出一半
共享ptr
和一半
弱ptr
(如上图所示)。

p不能在该代码中有效地销毁,因为父级必须仍然存在:我们在对其调用的成员函数中。我认为子构造函数应该使用一个共享的ptr,用它来恢复child2指针,然后存储一个指向父级的弱指针。或者取两个参数。如果您知道调用者有一个共享的\u ptr,并且被调用者需要使用该值,那么将其作为弱\u ptr传递就没有什么意义了。如果其他地方有创建子对象的代码,并且只有一个弱ptr,那么可能一个采用弱ptr的构造函数是正确的。关于构造函数采用共享ptr然后转换为弱ptr进行存储的好建议-顺便说一句,我会通过“采用两个参数”考虑一下(当然会稍微整理代码),我的意思是一个给父母,一个给孩子。重新阅读时,我注意到它可以作为一个共享的ptr和一个弱的ptr读给父对象,但这不是我的意思。@SteveJessop“既然父对象必须仍然存在”,你一开始就不需要智能指针。使用常规指针是显而易见的、自然的、简单的、有效的解决方案。可能重复:不是重复。我用一个弱的ptr来打破父母和孩子之间的循环引用。我的问题是关于将共享的ptr存储到兄弟姐妹,通过父代检索。严重依赖共享的ptr不是一个好主意。这是一个专门的工具,考虑到某些用例。在您的示例中,为什么不将子对象的作用域设为\u ptr,并将父对象的句柄设为原始指针?如果存在循环依赖项,将链接更改为弱指针会改变依赖项的性质,可能会消除该问题。所以它当然是一个选项,即使还有其他选项。@DennisZickefoose如果您有循环依赖项,就不能使用弱引用。如果您可以使用弱引用,这证明您确实没有循环依赖关系:因为您可以处理一个链接可能被破坏的事实,所以它不是依赖关系。如果你不需要某样东西,就不要依赖它。“将链接更改为弱指针会更改依赖项的性质”是的,它会将依赖项的性质更改为:而不是依赖项。这很有帮助。我看到你在一些关于共享指针的问题上咆哮,我有点同意。弱ptr在一些情况下有帮助,但不能解决问题