我可以使用C++ Boost shared_ptr编程,像在Java中一样不必关心内存管理吗?

6

我已经有一段时间没写C/C++了,现在我需要它的效率去完成一个项目。

据我理解,shared_ptr的作用是当我需要时删除对象。所以,如果我的对象有一个shared_ptr向量,那么在析构函数中,我就不用担心迭代这个向量并删除每个元素了?换句话说,只要使用这些,我就不用担心内存管理了?还是我完全误解了这一点?这听起来太美好了。


听起来你真正想要的是boost::ptr_vector。该向量拥有指针并在被覆盖或向量被销毁时删除它。 - Martin York
3
如果你像写Java一样编程,你怎么会认为你会得到“C++的效率”呢?并没有什么魔法。一个程序之所以快,并不是因为它是用C++编写的,而是因为它被写成了高效的形式。假装C++是Java只会让你在可维护性和性能方面两败俱伤。 - jalf
3个回答

11
你必须理解,共享指针是使用引用计数实现的,这意味着如果你的指针图中存在循环引用,那么对象将不会被释放。也就是说,如果a指向b,b指向a,但没有其他指针指向a或b,那么a和b都具有“1”的引用计数,因此它们都不会被释放。
Boost提供了弱指针来解决这个问题,它允许你存储一个指向共享对象的指针而不增加它的引用计数。弱指针提供了一层安全性,试图在共享指针释放后解除引用该指针将引发异常,而不是使程序崩溃。
从性能角度来看,共享指针也非常昂贵(至少与原始指针相比),但最好在分析器识别瓶颈后再删除它们,而不是到处都不使用它们。
除此之外,它们非常有用于管理动态分配的对象。
编辑:另一个需要注意的地方(在boost页面上已经提到)是要避免“临时”共享指针。
func(A(), boost::shared_ptr<B>(new B));

因为编译器可以对此进行优化

tmp1 = new B;
tmp2 = A();
tmp3 = boost::shared_ptr<B>(tmp1)
func(tmp2,tmp3)

这段代码乍一看可能没什么问题,但如果 A() 抛出异常,那么 B 已经被分配了,但是 shared_ptr 还没有持有它,因此指针永远不会被释放。


+1 提到循环引用。同时,不要忘记它们可以简化编写异常安全代码的过程。 - Khaled Alshaya
这个回答在技术上是正确的,但它忽略了一个问题,那就是以这种方式编码,你将失去使用C++的初衷——提高效率。 - jalf
但是,您始终可以优化掉在时间关键代码中引起问题的共享指针。这样做比另一种方式要好得多。 - Adam Bowen
此外,我认为性能与实际问题无关 - 另一个转向C++的程序员可能会有相同的内存管理问题。我确实同意仅仅在C++中编码可能不会给您带来任何性能上的好处。 - Adam Bowen

6
你可以这样做,但一般来说这是个坏主意。首先,你可能会失去你认为会获得的一些或全部效率。
更重要的是,听起来你正试图避免设计你的代码。Java有垃圾回收机制,所以你不必担心内存管理问题,但你仍然应该关注对象寿命。如果你不清楚谁拥有什么,你很可能最终会得到混乱的设计。
C++在对象寿命方面给你提供了许多选项,不是每个复杂对象都需要分配到堆上。shared_ptr应该用于需要共享所有权的对象(正如它的名字所示),但这应该是一个积极的设计决策。如果不需要共享或可转让所有权,则有更好的方法拥有一个对象。

4

这里,我发布了关于不同的自动内存管理策略的信息。它解释了GC和引用计数之间的主要区别。

现代C++开发人员很少使用手动内存(或资源)管理之类的东西。我们大多数人使用RAII习惯用法来代替(请参阅 http://en.wikipedia.org/wiki/RAII ),即一些实用程序类帮助我们处理资源。

Shared_ptr是一种伟大的技术,可以简化例行的内存/资源管理任务。这种技术有一些缺点(无法处理循环结构,并且它在时间和空间方面具有性能开销。对于引用上的每个操作,实现现在将执行算术操作 - 在分离情况下,还有条件指令。此外,每个对象必须扩展一个额外的字段来保存计数)。

最近我参与了一个相当大的项目(只是我的部分包含了200多个类),我从未(绝对没有)手动使用过operator delete。这样的工具简化了编码、调试、维护,并显著降低了开发成本。最近我参与了一个类似的项目(具有非常相似的业务逻辑和架构),但是使用的是C#。我可以真诚地告诉你:它们非常相似(首先,因为C++项目中的自动内存管理)。

顺便说一句,没有每个C++程序员都知道,shared_ptr可以在自定义删除器的情况下用于自动资源管理(不仅仅是自动内存管理)。


+1 用于自定义删除器。它们非常适合在来自 C API 的资源上实现 RAII。Boost 几乎没有记录该功能。 - Emile Cormier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接