【发布时间】:2020-08-26 14:38:48
【问题描述】:
我有以下TreeNode 类,它可以存储对其父节点的引用以及指向其所有子节点的指针向量。
树节点
class TreeNode : public std::enable_shared_from_this<TreeNode>
{
private:
int val_;
std::weak_ptr<TreeNode> parent_;
std::vector<std::shared_ptr<TreeNode>> children_;
public:
TreeNode(int val) : val_(val) {}
void addChild(std::shared_ptr<TreeNode> child)
{
child->parent_ = shared_from_this();
children_.push_back(std::move(child));
}
const int& getVal() const
{
return val_;
}
std::weak_ptr<TreeNode> getParent()
{
return parent_;
}
};
parent_ 存储为weak_ptr,这样父子之间就没有循环依赖/内存泄漏。
主要
int main(int argc, char** argv) {
std::shared_ptr<TreeNode> parent = std::make_shared<TreeNode>(1);
std::shared_ptr<TreeNode> child = std::make_shared<TreeNode>(2);
parent->addChild(child);
// child->getParent()->getVal(); not possible
return 0;
}
使用此类时,我想访问任何节点的父节点的值(...否则为什么要存储父节点),但由于 parent_ 是 weak_ptr,我无法调用任何成员函数它。
我知道这方面存在一些“黑客行为”,例如使用lock 从weak_ptr 中提取shared_ptr,但我觉得这会使API 变得笨拙。我想知道返回 weak_ptr 的推荐 C++11 方法是什么,它仍然可以使用。
编辑:
我可能不应该将 lock 称为“黑客”,而是从 API 的角度来看不够优雅。
例如,如果我想访问parent_,我必须这样做
主要
if (!child->getParent()->expired())
{
std::cout << child->getParent()->lock()->getVal() << std::endl;
}
这似乎相当冗长,所以我想知道是否有任何语言功能可以利用来避免做所有这些。
【问题讨论】:
-
这不是黑客行为。为了使用
weak_ptr指向的内容,您必须确认指向的对象 sill 存在,并确保它在您使用时继续存在。这就是lock的用途。 -
是什么让您认为
lock是黑客?weak_ptr没有它就无法使用 -
对不起,我不应该使用“hack”这个词,我已经编辑了原始帖子以说明为什么这可能会导致冗长的 API。
-
与你的橡皮鸭讨论如果在
if (!child->getParent()->expired())确认对象仍然存在后立即销毁对象会发生什么。 -
时髦。你明白发生了什么。很高兴我没有尝试正式回答这个问题。据我所知,没有内置的帮助程序,这将违反 C++ 的规定,您只需为您要求的政策付费,以默默地暗示锁定。我承认这该死的有用,但你不必承认你正在支付转换税。但既然你知道打电话给
getParent的人会和那个父母做点什么,我会返回一个shared_ptr并将lock隐藏在getParent中。
标签: c++ c++11 shared-ptr smart-pointers