如何在我的构造函数中将weak_ptr分发给这个

How do I hand out weak_ptrs to this in my constructor?

本文关键字:ptr weak 我的 构造函数      更新时间:2023-10-16

我正在创建一个将成为DAG一部分的类。构造函数将获取指向其他实例的指针,并使用它们初始化依赖项列表
在初始化依赖项列表后,它只能被缩短——实例永远不能作为其自身或其任何子项的依赖项添加。

::std::shared_ptr是处理此问题的自然条件。参考计数用于处理DAG。

不幸的是,依赖项需要知道它们的依赖项——当一个依赖项被更新时,它需要告诉它的所有依赖项
这创建了一个可以用::std::weak_ptr打破的琐碎循环。依赖项可以忘记那些消失的依赖项。

但我找不到一种方法让依赖项在构建时为自己创建::std::weak_ptr

这不起作用:

object::object(shared_ptr<object> dependency)
{
     weak_ptr<object> me = shared_from_this();
     dependency->add_dependent(me);
     dependencies_.push_back(dependency);
}

该代码导致在构造函数退出之前调用析构函数。

有什么好方法可以解决这个问题吗?我对仅使用C++11的解决方案非常满意。

使用函数来构建图的节点,而不是构造函数。

std::shared_ptr<Node> mk_node(std::vector<std::shared_ptr<Node>> const &dependencies)
{
    std::shared_ptr<Node> np(new Node(dependencies));
    for (size_t i=0; i<dependencies.size(); i++)
        dependencies[i].add_dependent(np);       // makes a weak_ptr copy of np
    return np;
}

如果将其设为static成员函数或Node类的friend,则可以将实际构造函数设为private

基本上,你不能。你需要一个shared_ptrweak_ptr来制作weak_ptr,很明显,self只能以weak_ptr的形式知道自己的shared_ptr(否则,计算引用没有意义(。当然,当对象还没有被构造时,就不可能有self-shared_ptr

你不能。

我想到的最好的方法是使构造函数私有化,并具有一个公共工厂函数,该函数向新对象返回shared_ptr;工厂函数然后可以在初始化CCD_ 15的对象后构造上调用私有方法。

我理解您的问题在概念上与垃圾收集问题有关。

GC是一个非模块化功能:它处理程序的一些全局属性(更准确地说,作为一个活动数据是程序内部的全局、非模块化属性-在某些情况下,你无法以模块化和组合的方式处理它。(。AFAIK、STL或C++标准库对全局程序功能没有太大帮助。

一个可能的答案可能是使用(或自己实现(垃圾收集器;如果您能够在整个程序中使用Boehm的GC,那么它可能对您有用。

您还可以使用GC算法(甚至复制世代算法(来处理您的问题。

不幸的是,依赖关系需要了解它们的依赖关系。这是因为当更新依赖项时,它需要告知其所有依赖项。还有一个琐碎的循环。幸运的是,这个循环可以用:std::weak_ptr来打破。依赖项可以忘记那些消失的依赖项。

听起来依赖项不能引用依赖项,除非依赖项存在。(例如,如果依赖项被破坏,依赖项也会被破坏——毕竟DAG就是这样(

如果是这种情况,您可以只分发普通指针(在本例中为this(。如果依赖项还活着,你永远不需要在依赖项内部进行检查,因为如果依赖项死了,那么依赖项也应该死了。

仅仅因为对象由shared_ptr所有并不意味着指向它的所有指针本身都必须是shared_ptrs或weak_ptrs——只是你必须定义指针何时无效的明确语义。

在我看来,这听起来像是你试图将不同的项目合并:一个对象(DAG中的一个节点(,并管理这些对象的集合。

class DAG { 
    class node {
        std::vector<std::weak_ptr<node> > dependents;
    public:
        node(std::vector<weak_ptr<node> > d) : dependents(d) {}
    };
    weak_ptr<node> root;
};

现在,DAG可能只持有weak_ptr<node>,而不是直接处理node的实例。然而,对于节点本身来说,这或多或少是无关紧要的。它需要维护任何密钥/数据等。,它包含,以及它自己的从属列表。

同时,通过将其嵌套在DAG内部(特别是如果我们将node的类定义设为DAG专用的(,我们可以最大限度地减少对node的访问,因此很少有其他代码与node有关。根据情况,您可能还想删除节点中编译器默认生成的一些(大多数?(函数(例如,默认ctor、复制ctor、赋值运算符(。

这也让我抓狂。

我考虑过采用使用指针打破循环的策略。。。但我真的没有发现这一点,因为我真的很喜欢当你在代码中看到weak_ptr时,它的意图是多么清晰(你知道它是用来打破循环的(。

现在我倾向于编写我自己的weak_ptr类。

也许这会有所帮助:

enable_shared_from_this继承,后者基本上保存一个weak_ptr。这将允许您使用this->shared_from_this();

shared_ptr知道查看类是否从类继承,并在指向对象时使用类weak_ptr(防止2个共享指针以不同方式计数引用(

更多信息:cppreference