在这种情况下,我应该使用智能指针吗?



我知道,首选规则是始终使用shared_ptr S或其他智能指针。但是,我不确定如何在没有std::make_shared复制CTOR的情况下确切实施它。我会详细说明:

问题

我想创建一个类似树的表达,例如:

struct foo{
    std::vector<foo*> v;
};

这使我可以做以下操作:

foo add(foo& f1, foo& f2){
    return foo {&f1, &f2};
}

很好,因为那时两个人将成为一个新节点的孩子。

我希望正确评估以下内容:

foo x, y;
auto z = add(x,y);
assert(z.v[0] == &x && z.v[1] == &y);

以这种方式,没有复制,一切都很好。但是,我们在这里有一个资源管理问题。

解决资源管理问题

如果这些元素分配在堆上,并且有人在不知不觉中可能会遇到内存泄漏。因此,最好的方法是将智能指针用于RAII:

struct foo{
    std::vector<std::shared_ptr<foo> > v;
};
foo add(foo& f1, foo& f2){
    return foo {std::make_shared<foo>(f1), std::make_shared<foo>(f2)};
}

这很好,但是我们在此处调用f1和f2的副本。假设复制需要很长时间,我们不想产生这一费用。

我们绝对不能:

foo add(foo& f1, foo& f2){
    return foo {std::shared_ptr<foo>(&f1), std::shared_ptr<foo>(&f2)};
}

因为每当我们在z = x+y中删除z时,我们都会在xy中调用delete,这可以在堆栈上分配。,我们绝对不想在堆栈上进行delete

那么在这种情况下我该怎么办?

让我知道我是否应该在上下文上提供更多信息。

通过智能指针接受。正确应用智能指针的概念意味着您必须考虑数据的所有权语义,而不是自动调用新/删除。

您接受对非const对象的引用。这并不意味着共享,仅修改对象。正如您正确指出的那样,只需为他们创建明智的指针就拼写灾难。

add的呼叫者(即使只是您)必须知道他们传递的数据即将共享。他们知道自己是否通过智能指针自己的唯一途径。因此,您应该将add更改为:

foo add(std::shared_ptr<foo> f1, std::shared_ptr<foo> f2){
    return foo{f1, f2};
}

现在, add的用户唯一有意炸毁了这一点。但是他们很可能不会。此外,现在表示用户在调用代码方面具有更大的灵活性。他们可以为通过的每个对象控制分配器和eleter。

相关内容

  • 没有找到相关文章

最新更新