为什么不应该使用对智能指针的引用?

Why shouldn't you use references to smart pointers?

本文关键字:指针 引用 智能 不应该 为什么      更新时间:2023-10-16

我记得在某个地方读到,使用对智能指针的引用可能会导致内存损坏。这仅仅是因为在智能指针被销毁后使用了它的引用吗?还是引用计数搞砸了?

感谢您澄清

假设您在这里谈论的是shared_ptr。。。

这仅仅是因为使用之后智能指针的引用它被摧毁了?

这是一个很好的答案。您可能也不完全知道引用引用的指针的生存期。

为了解决这个问题,您需要研究boost::weak_ptr。它不参与引用计数。当你需要使用它时,它会给你一个shared_ptr,一旦你使用完它,它就会消失。它还会让你知道什么时候收集了refered-to指针。

来自weak_ptr文档

weak_ptr类模板存储对对象的"弱引用"已由shared_ptr管理。到访问对象,weak_ptr可以使用转换为shared_ptrshared_ptr构造函数或成员功能锁定。当最后对象的shared_ptr消失对象被删除,尝试从weak_ptr获得sharedptr引用已删除的对象将失败:构造函数将引发类型为的异常boost::bad_weak_ptr,以及weak_ptr::lock将返回一个空shared_ptr。

请注意,方法expired()还会告诉您ptr是否仍然存在。

使用智能指针(或任何分配管理对象)时,您指望构造函数/析构函数中定义的行为来管理refs/derefs/locks/unlocks。因此,这些类型的对象必须是真正的对象才能正常执行。当使用对此类对象(或指针)的引用时,您绕过了该机制(并要求wedgee)。

在许多情况下,引用智能指针是个好主意。一个明显的例子是智能指针类本身的赋值方法,它接受对另一个智能指针的引用作为其参数。

制作一个接受智能指针引用的方法意味着该参数不会增加智能指针的内部引用计数。这可以提高性能,但可能不会太多。此外,该方法还不能对引用或原始智能指针执行许多操作。如果你知道这些东西是什么并避免它们,那么通过参考就可以了。当然,智能指针的目的是避免必须知道这些事情。

此外,如果您有一个方法将修改智能指针参数的值,则需要作为引用传递,就像任何其他类型一样。

智能指针的"智能"部分由智能指针类的构造函数、析构函数、赋值运算符和其他函数管理。通过使用引用,可以规避这些操作——初始化引用时不会调用构造函数,当引用超出范围时也不会调用析构函数。

从本质上讲,对智能指针的引用是一个愚蠢的指针,后者会带来所有风险和麻烦。

我们有定制的智能指针,我们总是习惯于传递一个"const-refssomething&"

它不递增或递减智能指针,因此,更重要的是,避免了对InterLockedIncrement/decrement的调用,这反过来又避免了内存围栏和所有相关的事情:总线锁定、缓存无效。。。

将对智能指针的引用传递到函数中是非常安全的,也是一个好主意。对象可能会消失,但智能指针不会,它会坐在那里说null,至少直到函数返回为止。这是在智能指针的作用域内对其进行别名的最佳方式。如果你使用一个带有const修饰符的引用,那么你就有了一个智能的观察引用:

const smart_ptr<T>&

有趣且有用的是,const阻止您使用引用,例如,使智能指针为null并删除对象,但它不会阻止原始智能指针使其自身为null,您的引用将反映这种变化。

从函数返回对智能指针的引用会带来各种麻烦。