的 share_ptr

我目前正在学习如何使用智能指针。然而,在做一些实验时,我发现了以下情况,我无法找到一个令人满意的解决方案:

假设 A 类的一个对象是 B 类的一个对象(子对象)的父对象,但是两个对象应该互相认识:

class A;
class B;


class A
{
public:
void addChild(std::shared_ptr<B> child)
{
children->push_back(child);


// How to do pass the pointer correctly?
// child->setParent(this);  // wrong
//                  ^^^^
}


private:
std::list<std::shared_ptr<B>> children;
};


class B
{
public:
setParent(std::shared_ptr<A> parent)
{
this->parent = parent;
};


private:
std::shared_ptr<A> parent;
};

问题是 A 类的对象如何将自身的 std::shared_ptr(this)传递给它的子对象?

Boost 共享指针(获取 ABC1的 boost::shared_ptr)有解决方案,但是如何使用 std::智能指针来处理这个问题呢?

73741 次浏览

std::enable_shared_from_this就是为了这个目的而存在的。您可以从它继承,并且可以从类内部调用 .shared_from_this()。此外,您在这里创建的循环依赖关系可能导致资源泄漏。这可以通过使用 std::weak_ptr来解决。因此,您的代码可能看起来如下(假设子代依赖于父代的存在,而不是父代的存在) :

class A;
class B;


class A
: public std::enable_shared_from_this<A>
{
public:
void addChild(std::shared_ptr<B> child)
{
children.push_back(child);


// like this
child->setParent(shared_from_this());  // ok
//               ^^^^^^^^^^^^^^^^^^
}


private:
// note weak_ptr
std::list<std::weak_ptr<B>> children;
//             ^^^^^^^^
};


class B
{
public:
void setParent(std::shared_ptr<A> parent)
{
this->parent = parent;
}


private:
std::shared_ptr<A> parent;
};

但是请注意,调用 .shared_from_this()要求在调用点 std::shared_ptr拥有 this。这意味着您不能再在堆栈上创建这样的对象,而且 一般来说不能从构造函数或析构函数中调用 .shared_from_this()

您的设计中有几个问题,这些问题似乎源于您对智能指针的误解。

智能指针用于声明所有权。你宣称父母双方拥有所有的孩子,但是每个孩子都拥有自己的父母,这违反了这一点。不可能都是真的。

此外,在 getChild()中返回弱指针。通过这样做,您可以声明调用方不应该关心所有权。这可能会非常有限,但是这样做的话,你必须确保当任何弱指针仍然存在的时候,孩子不会被破坏,如果你使用智能指针,它会自己被排序。

最后一件事。通常,在接受新实体时,通常应该接受原始指针。智能指针对于在父级之间交换子级有自己的含义,但是对于一般用法,您应该接受原始指针。