我目前正在尝试学习如何使用智能指针。然而,在做一些实验时,我发现了以下情况,我无法找到一个令人满意的解决方案:
想象一下,你有一个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共享指针(Getting a boost::shared_ptr
for this
)有解决方案,但如何使用std::
智能指针处理这个问题?
答案 0 :(得分:137)
仅为此目的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()
要求this
在呼叫点拥有std::shared_ptr
。这意味着你不能再在堆栈上创建这样的对象了,通常不能从构造函数或析构函数中调用.shared_from_this()
。
答案 1 :(得分:6)
您在设计中遇到了一些问题,这些问题似乎源于您对智能指针的误解。
智能指针用于声明所有权。你通过声明父母既拥有所有孩子,又让每个孩子拥有它的父母来打破这一点。两者都不可能是真的。
此外,您将在getChild()
中返回弱指针。通过这样做,您宣称调用者不应该关心所有权。现在这可能是非常有限的,但是通过这样做,你必须确保有问题的孩子在任何弱指针仍然被保持时不会被破坏,如果你使用智能指针,它将自己整理出来
最后一件事。通常,当您接受新实体时,通常应该接受原始指针。智能指针对于在父母之间交换孩子有其自己的意义,但是对于一般用法,你应该接受原始指针。