[英]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
,我们都会在x
和y
每一个上调用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.