我记得在某处读过使用对智能指针的引用会导致内存损坏。这仅仅是因为在智能指针被销毁后使用了它的引用吗?还是引用计数搞砸了?
感谢您的澄清
假设您在这里谈论 shared_ptr ......
这仅仅是因为在智能指针被销毁后使用了它的引用吗?
这是一个很好的答案。您可能也不绝对知道您的引用所引用的指针的生命周期。
为了解决这个问题,您需要查看 boost::weak_ptr。它不参与引用计数。当您需要使用它时,它会为您提供一个 shared_ptr,一旦您完成它就会消失。它还会让您知道何时收集了引用的指针。
来自weak_ptr文档
weak_ptr 类模板存储了对已由 shared_ptr 管理的对象的“弱引用”。要访问对象,可以使用 shared_ptr 构造函数或成员函数 lock 将 weak_ptr 转换为 shared_ptr。当对象的最后一个 shared_ptr 消失并且对象被删除时,尝试从引用已删除对象的 weak_ptr 实例获取 shared_ptr 将失败:构造函数将抛出 boost::bad_weak_ptr 类型的异常,并且 weak_ptr: :lock 将返回一个空的 shared_ptr。
注意 expired() 方法也会告诉你你的 ptr 是否还在。
当使用智能指针(或任何分配管理对象)时,您指望在构造函数/析构函数中定义的行为来管理 refs/derefs/locks/unlocks。因此,这些类型的对象必须是真正的对象才能正确执行。当使用对此类对象(或指针)的引用时,您正在绕过机制(并要求 wedgie)。
在很多情况下,对智能指针的引用是个好主意。一个明显的例子是智能指针类本身的赋值方法,它接受对另一个智能指针的引用作为其参数。
制作一个接受智能指针引用的方法意味着该参数不会增加智能指针的内部引用计数。这可以提高性能 - 但可能不会很多。此外,该方法无法对引用或原始智能指针做很多事情。如果您知道这些东西是什么并避免它们,那么通过引用传递就可以了。当然,智能指针的目的是避免必须知道这些事情。
此外,如果您有一个将修改智能指针参数值的方法,则需要作为引用传递,就像使用任何其他类型一样。
智能指针的“智能”部分由智能指针类的构造函数、析构函数、赋值运算符和其他函数管理。通过使用引用,您可以绕过这些操作——当您的引用被初始化时构造函数不会被调用,而当您的引用超出范围时析构函数不会被调用。
本质上,对智能指针的引用是一个哑指针,具有后者所带来的所有风险和陷阱。
我们有定制的智能指针,我们总是养成传递“const refsomething &”的习惯
它不会增加或减少智能指针,因此 - 更重要的是 - 避免了对 InterLockedIncrement/Decrement 的调用,这反过来又避免了内存围栏以及与之相关的所有事情:总线锁定、缓存失效、.. .
将对智能指针的引用传递给函数是非常安全的,并且是一个好主意。对象可能会消失,但智能指针不会,它会坐在那里说 null 至少直到函数返回。这是在其范围内为智能指针起别名的最佳方式。如果您在引用的内容上使用带有 const 修饰符的引用,那么您将拥有一个智能观察引用:
const smart_ptr<T>&
有趣且有用的是, const 会阻止您使用引用来表示智能指针为空并删除对象,但它不会阻止原始智能指针自身为空,并且您的引用将反映该更改。
从函数返回对智能指针的引用会带来各种麻烦。