指针,智能指针或共享指针?

我正在用普通的指针进行编程,但是我听说过像Boost这样的实现智能指针的库。 我也看到,在Ogre3D渲染引擎中有一个共享指针的深度使用。

这三者之间究竟有什么区别,我应该坚持只使用它们的一种?

Sydius相当好地描述了types:

  • 普通的指针就是这样的 – 它们指向某个地方的内存。 谁拥有它? 只有评论会让你知道。 谁释放它? 希望在某个时候的所有者。
  • 智能指针是一个涵盖了许多types的总括术语; 我假设你的意思是使用RAII模式的scoped指针。 它是一个包装指针的堆栈分配对象; 当它超出范围时,它会调用它所包装的指针上的删除。 它“拥有”包含的指针,它负责在某个时候删除它。 它们允许你获得一个原始的引用,将它们包装的指针传递给其他方法,以及释放指针,允许其他人拥有它。 复制它们没有意义。
  • 共享指针是一个包含指针的堆栈分配对象,所以你不必知道谁拥有它。 当内存中最后一个对象的共享指针被破坏时,被包装的指针也将被删除。

如何使用它们? 您将要大量使用作用域指针或共享指针。 在您的应用程序中运行多less个线程? 如果答案是“潜在的很多”,共享指针可能会成为一个性能瓶颈,如果在任何地方使用。 原因是创build/复制/破坏共享指针需要是一个primefaces操作,如果有许multithreading在运行,这可能会妨碍性能。 然而,这并不总是这样 – 只有testing才能确定地告诉你。

有一个争论(我喜欢)与共享指针有关 – 通过使用它们,您允许程序员忽略谁拥有指针。 这可能会导致棘手的情况下循环引用(Java将检测这些,但共享指针不能)或一般程序员懒惰在一个大的代码库。

有两个原因使用范围指针。 第一个是简单的exception安全和清理操作 – 如果你想保证一个对象被清理,无论面对什么exception,你不想堆栈分配这个对象,把它放在一个范围内的指针。 如果操作成功,您可以随意将其转移到共享指针,但同时用范围指针保存开销。

另一种情况是当你想要明确的对象所有权。 有些队喜欢这个,有些则不喜欢。 例如,一个数据结构可能会返回指向内部对象的指针。 在一个作用域的指针下,它将返回一个原始的指针或引用,应该被视为一个弱引用 – 在拥有它的数据结构被破坏后访问该指针是一个错误,并且删除它是一个错误。 在一个共享指针下,拥有对象不能破坏它返回的内部数据,如果有人仍然持有它的话 – 这可能会使资源打开时间超过必要的时间,或者根据代码而更糟。

术语“智能指针” 包括共享指针,自动指针,locking指针等。 你的意思是说自动指针(更模糊地称为“拥有指针”),而不是智能指针。

哑指针(T *)永远不是最好的解决scheme。 他们让你做明确的内存pipe理,这是冗长,容易出错,有时几乎不可能。 但更重要的是,他们不表示你的意图。

自动指针在销毁时删除指针。 对于数组,更喜欢像vector和deque这样的封装。 对于其他对象,很less需要将它们存储在堆上 – 只需使用本地和对象组合。 对于返回堆指针的函数,例如工厂和多态返回,仍然需要自动指针。

当最后的共享指针被销毁时,共享指针会删除指针。 当您想要一个不需要考虑的开放式存储scheme时,这种方法非常有用,因为根据具体情况,预期的使用期限和所有权可能差异很大。 由于需要保持(primefaces)计数器,它们比自动指针慢一点。 有些人说开玩笑说共享指针是为那些不能devise系统的人们自己判断的。

对于共享指针的重要对象,也可以查找弱指针。

智能指针在超出范围之后会自行清除(从而消除大多数内存泄漏的恐惧)。 共享指针是智能指针,用于保存指针存在多less个实例的计数,并且只在计数达到零时清除内存。 通常,只使用共享指针(但是一定要使用正确的types – 对于数组有一个不同的)。 他们和RAII有很多关系。

为了避免内存泄漏,您可以使用智能指针。 在C ++中基本上有2种不同types的智能指针

  • 引用计数(例如,boost :: shared_ptr / std :: tr1:shared_ptr)
  • 非引用计数(例如boost :: scoped_ptr / std :: auto_ptr)

主要区别是引用计数智能指针可以被复制(并在std ::容器中使用),而scoped_ptr不能。 非引用计数指针几乎没有开销或根本没有开销。 引用计数总是会引入某种开销。

(我build议避免auto_ptr,如果使用不正确,它有一些严重的缺陷)

为了给Sydius的答案增加一点点,智能指针通常会提供一个更稳定的解决scheme,捕捉许多容易犯的错误。 生指针会有一些性能优势,在某些情况下可以更灵活。 链接到某些第三方库时,您也可能被迫使用原始指针。