我已经陷入困境:我编写了一个树形图结构,其中每一层都包含一个指向前一层(超类型)指针的向量和指向后续(子类型)层的指针。
你可以想象,这是一个循环参考:
[last] -(super)-> [current]
[current] -(sub)-> [last]
当我分配新的layer
时,请确保将其移至current
当我最后重新分配给当前时,我再次移动它。
然而,这并没有解决泄漏,实际上我发现的唯一解决方案是使用原始指针。
这是一个缩小代码大部分的缩小示例:
struct layer
{
std::unordered_set<std::string> words;
std::vector<layer*> sub_classes;
std::vector<layer*> super_classes;
}
实际迭代为wordnet senses
,填充树形图。
执行hypernyms
的函数(例如,单词的超类型)是:
void iterate_sense(
Synset * sense,
std::shared_ptr<layer> last,
graph & rhs,
int lexical
)
{
std::shared_ptr<layer> current;
while (sense && last)
{
current = std::move(get_layer(sense));
last->super_classes.push_back(current.get());
current->sub_classes.push_back(last.get());
if (sense->ptrlist)
{
iterate_sense(sense->nextss,
last,
rhs, lexical);
}
last = std::move(current);
sense = sense->ptrlist;
}
}
这些指针归另一个类graph
所有。
当我在layer
std::vector<std::shared_ptr<layer>> sub_classes;
std::vector<std::shared_ptr<layer>> super_classes;
Valgrind报告丢失了字节。
正确或优雅解决此问题的方法是什么? 我假设使用原始指针不是最好的解决方案吗?
我是否正确假设所有者graph
丢失的那一刻,
原始指针将变为无效?
这不是一个大问题,因为layers
本身只存在于图表中。
我已经阅读了SO和谷歌,通过std::weak_ptr
和std::shared_ptr
的组合正确使用,但我不明白在这种情况下如何使用weak_ptr
答案 0 :(得分:2)
智能指针,是关于所有者的船只。它说谁负责某个对象。语义基本上分为如下:
std::unique_ptr<>
:一个函数/对象是对象的所有者和负责人。std::shared_ptr<>
:几个函数/对象是对象的所有者和负责人。raw pointer
:其他人是该对象的所有者并负责。在您的情况下,我建议遵循语义:图层是其子图层的所有者。儿童不是其父母的所有者。
在此之后我会使用
std::vector<std::unique_ptr<layer>> sub_classes;
std::vector<layer*> super_classes;e
对于iterate_sense
,我建议使用以下签名:
void iterate_sense(
Synset * sense,
layer* last,
graph & rhs,
int lexical
)
此函数未完全或部分拥有变量last
中的对象。它只被授予有限的访问权限。
不确定graph
拥有这些指针的方式。如果graph
实际上是std::unique_ptr<>
的所有者,则您只能在raw pointers
中使用layers
。这正是使用它的正确方法。
在某些情况下,可以使用std :: weak_ptr&lt;&gt;打破循环引用。我建议不要使用它们。如果您对数据结构进行了简洁的设计,通常很容易说出谁是对象的责任人/所有者。没有那么多的情况不明确。在这些不清楚的情况下,如果一个对象被多个其他对象管理/拥有,则需要std :: shared_ptr&lt;&gt;。在这些情况下,您可能需要访问一个您不知道它是否仍然存在的对象。在这种情况下,您可能希望使用std :: weak_ptr&lt;&gt;。