繁体   English   中英

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

[英]Should I use smart pointers in this situation?

我知道转到规则是始终使用shared_ptr或其他智能指针。 但是,我不确定在不使用std::make_shared复制代码的情况下如何准确地实现它。 我会详细说明:

问题

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

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的副本ctor 假设复制需要很长时间,并且我们不想承担该费用。

我们绝对不能:

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

因为每当我们删除z z = x+y中的z = x+y ,我们都会在xy每一个上调用delete ,它们可以分配在堆栈上。 而且我们绝对不想delete堆栈中的内容。

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

让我知道是否应提供有关上下文的更多信息。

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

您接受对非常量对象的引用。 这并不意味着共享,仅意味着对象的修改。 正如您正确指出的那样,仅创建指向它们的智能指针就意味着灾难。

add的调用者(即使只有您自己)也必须知道他们传递的数据即将被共享。 他们知道的唯一方法是他们是否自己传递了智能指针。 因此,您应该add更改为:

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

现在, add用户唯一可以炸毁它的方法是故意的。 但是他们很可能不会。 此外,现在所说的用户在调用您的代码时具有更大的灵活性。 他们可以控制所传递的每个对象的分配器和删除器。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM