如何在我的构造函数中将weak_ptr分发给这个
How do I hand out weak_ptrs to this in my constructor?
我正在创建一个将成为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_ptr
或weak_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
- CLANG 编译器 说:变量"PTR"可能未初始化
- 在以唯一ptr为值的C++映射中,动态内存何时会被销毁
- 将 ptr 传递给 ptr 到 A 作为参数传递给 A 的函数是不好的做法吗?
- 为共享 ptr 向量实现复制 c'tor?
- 字符和整数中 **(ptr+1) 的值差异
- C++:在不中断共享的情况下通过引用传递共享 PTR?
- 为什么"weak.lock()"返回"nullptr" "auto weak=std::make_shared<int>(42);"的定义?
- 如何将派生类从基 ptr 分配给 nlohmann::json
- 引用 std::shared:ptr 以避免引用计数
- 为什么我不能在不进行任何转换的情况下将浮点数放入任何类型的 ptr 中?
- 在调用函数时,ptr** 和 ptr*& 之间是否有区别,或者首选C++?
- 另一种类型的智能ptr,比如具有弱refs的unique_ptr
- 尝试打印出 *ptr++ 的值,以了解它是如何工作的
- 如何控制共享 ptr 引用计数?
- C++中的指针否定 (!ptr == NULL)
- 从const ptr*转换为ptr*时出现问题
- 这是MSVC 2013中具有共享PTR的单例的正确实现吗?
- 对唯一 ptr 无效读取的引用向量
- C++ 类型转换基础 PTR 到派生 PTR 保存在引用类中
- 为什么使用模板生成的函数具有"weak"符号类型?