在使用智能指针的C++项目中,例如boost::shared_ptr
,使用" this
" 的好设计理念是什么?
考虑一下:
存储任何智能指针中包含的原始指针以供以后使用是危险的.您已放弃对对象删除的控制,并信任智能指针以在正确的时间执行此操作.
非静态类成员本质上使用this
指针.它是一个原始指针,无法更改.
如果我存储this
在另一个变量或把它传递给这有可能保存它供以后或在回调绑定它的另一个功能,我创建的引入当有人决定做一个共享指针,以我的课的错误.
鉴于此,我何时适合明确使用this
指针? 是否有设计范例可以防止与此相关的错误?
在使用智能指针的C++项目中
这个问题实际上与智能指针无关.它只涉及所有权.
他们没有改变所有权的概念,特别是.需要在您的计划中拥有明确的所有权,所有权可以自愿转移,但不能由客户承担.
您必须了解智能指针(也包括锁和其他RAII对象)表示一个值和一个WRT此值同时关系.A shared_ptr
是对象的引用并建立关系:在此之前不得销毁该对象shared_ptr
,并且当它shared_ptr
被销毁时,如果它是对该对象别名的最后一个对象,则必须立即销毁该对象.(unique_ptr
可以视为根据shared_ptr
定义存在零别名的特殊情况,因此unique_ptr
始终是对象别名的最后一个.)
建议使用智能指针,因为它们只表示变量和函数声明.
智能指针只能表达定义明确的设计,它们不会消除定义所有权的需要.相反,垃圾收集消除了定义谁负责内存释放的需要.(但不要忽视定义谁负责其他资源清理的需要.)
即使在非纯函数式垃圾收集语言中,您也需要明确所有权:如果其他组件仍需要旧值,则不希望覆盖对象的值.在Java中尤其如此,其中可变数据结构的所有权概念在线程程序中极为重要.
使用原始指针并不意味着没有所有权.它只是没有变量声明描述.它可以在评论,设计文档等中描述.
这就是为什么许多C++程序员认为使用原始指针而不是足够的智能指针是次要的:因为它的表达力较差(我故意避免使用"好"和"坏"这两个术语).我相信Linux内核可以用一些C++对象来表达关系.
您可以使用或不使用智能指针来实现特定设计.适当地使用智能指针的实现将被许多C++程序员认为是优越的.
你真正的问题在C++项目中,使用"this"的优秀设计理念是什么?
那太模糊了.
存储原始指针以供以后使用是危险的.
为什么需要指针供以后使用?
您已放弃对对象删除的控制,并信任负责的组件在适当的时间执行此操作.
实际上,某些组件负责变量的生命周期.你不能承担责任:必须转移.
如果我将它存储在另一个变量中或者将它传递给另一个可能存储它以便稍后存储或者在回调中绑定它的函数,我就会创建在任何人决定使用我的类时引入的错误.
显然,由于调用者没有被告知该函数将隐藏指针并在稍后使用它而没有调用者的控制,因此您正在创建错误.
解决方案显然是:
转移责任来处理对象到函数的生命周期
确保指针仅在调用者的控制下保存和使用
仅在第一种情况下,您可能最终在类实现中使用智能指针.
我认为你的问题是你正在努力使用智能指针使问题复杂化.智能指针是使事情变得更容易而不是更难的工具.如果智能指针使您的规范变得复杂,那么就简单的事情重新考虑您的规范.
在出现问题之前,不要尝试将智能指针作为解决方案.
仅引入智能指针来解决特定明确定义的问题.因为您没有描述特定明确定义的问题,所以不可能讨论特定的解决方案(涉及智能指针).
虽然我没有一般的答案或一些成语,但有boost::enable_shared_from_this
.它允许您获取一个shared_ptr来管理已由shared_ptr管理的对象.因为在成员函数中你没有引用那些管理shared_ptr的函数,所以enable_shared_ptr允许你获得一个shared_ptr实例,并在你需要传递this指针时传递它.
但是这不能解决this
从构造函数中传递的问题,因为当时没有shared_ptr管理你的对象.
正确使用的一个例子是return *this;
在operator ++()和operator <<()之类的函数中.
当您使用智能指针类时,直接暴露" this
" 是危险的.有一些与之相关的指针类boost::shared_ptr
可能有用:
boost::enable_shared_from_this
提供使对象返回指向其自身的共享指针的能力,该指针使用与该对象的现有共享指针相同的引用计数数据
boost::weak_ptr
与共享指针一起使用,但不保存对象的引用.如果所有共享指针都消失并且对象被释放,则弱指针将能够告诉该对象不再存在并且将返回您NULL
而不是指向无效内存的指针.您可以使用弱指针来获取指向有效引用计数对象的共享指针.
当然,这些都不是万无一失的,但它们至少会使您的代码更加稳定和安全,同时为您的对象提供适当的访问和引用计数.