如何在构造函数中将weak_ptrs传递给它?

时间:2011-11-15 17:50:09

标签: c++ c++11 shared-ptr

我正在创建一个将成为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的解决方案非常满意。

8 个答案:

答案 0 :(得分:9)

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

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成员函数或friend类的Node,则可以创建实际的构造函数private

答案 1 :(得分:5)

基本上,你不能。您需要shared_ptrweak_ptr来制作weak_ptr,显然,自我只能以shared_ptr的形式了解自己的weak_ptr(否则就是没有必要计算参考)。当然,当对象尚未构建时,可能没有自我shared_ptr

答案 2 :(得分:1)

我理解您的问题在概念上与garbage collection问题有关。

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

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

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

答案 3 :(得分:1)

你做不到。

我提出的最好的方法是将构造函数设为私有,并使用公共工厂函数将shared_ptr返回给新对象;然后,工厂函数可以在构造后调用私有方法,初始化weak_ptr

答案 4 :(得分:1)

  

不幸的是,依赖关系需要知道他们的家属。这是因为当更新依赖项时,它需要告知所有依赖项。而且有一个微不足道的循环。幸运的是,这个循环可以用:: std :: weak_ptr打破。依赖关系可以忘掉那些消失的家属。

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

如果是这种情况,你可以发出简单的指针(在这种情况下,this)。如果依赖者还活着,你永远不需要检查依赖内部,因为如果依赖者死了,那么依赖也应该死了。

仅仅因为该对象归shared_ptr所有并不意味着它自己的所有指针都必须是shared_ptrs或weak_ptrs - 只需要定义关于指针何时失效的清晰语义。

答案 5 :(得分:1)

在我看来,你正试图将某些不同的项目混为一谈:一个对象(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,copy ctor,赋值运算符)。

答案 6 :(得分:0)

这也让我疯狂。

我考虑采用使用指针打破周期的策略......但是我真的没有找到这个因为我真的很喜欢当你在代码中看到它时,weak_ptr的意图是多么明确(你知道它在那里打破周期。)

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

答案 7 :(得分:-1)

也许这会有所帮助:

继承自 enable_shared_from_this ,基本上持有weak_ptr。 这样您就可以使用this->shared_from_this();

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

有关它的更多信息: cppreference