在C++中管理内存所有权的最佳方法是什么?共享指针或其他机制?

Pat*_*ick 2 c++ shared-ptr c++11

在一段新代码中,我有几个不同的类,它们互相引用.这样的事情(这不是我的实际情况,而是一个类似的例子):

class BookManager
   {
   ...
   };

class Book
   {
   public:
      void setBookManager(BookManager *bookManager) {m_bookManager = bookManager;}
   private:
      BookManager *m_bookManager;
   };
Run Code Online (Sandbox Code Playgroud)

每本书都指的是书籍管理员,但问题是许多书籍都有自己特定的BookManager,但有些书籍可能会共享一个共同的BookManager.

调用者并没有真正指定Book应该对其BookManager做什么,但在大约90%的情况下,BookManager可以与Book一起销毁.在大约10%的情况下,相同的BookManager可以重复用于多本书籍,并且不得使用书籍删除BookManager.

在这些90%的情况下,将BookManager与Book一起删除是很方便的,因为Book :: setBookManager的调用者不再需要记住BookManager.它只是因为书本身而死.

我看到两种解决方案可供选择.

首先是广泛使用共享指针.如果调用者之后在BookManager中不再感兴趣,则它不会保留共享指针.如果它仍然对它感兴趣,或者它希望BookManager在多本书上共享,它会保留共享指针并将其传递给那些多本书.

第二种方法是明确告诉本书如何处理书籍的所有权,如下所示:

class Book
   {
   public:
      void setBookManager(BookManager *bookManager, book takeOwnership=true)
         {
         m_bookManager = bookManager;
         m_hasOwnership = takeOwnership;
         }
      ~Book()
         {
         if (m_hasOwnership && m_bookManager) delete m_bookManager;
         }
   private:
      BookManager *m_bookManager;
      bool m_hasOwnership;
   };
Run Code Online (Sandbox Code Playgroud)

第二种解决方案似乎更容易,并允许我们使用正常的指针语法(BookManager *而不是std::shared_ptr<BookManager>),但它似乎比共享指针方法更"干净".

另一种选择可能是在BookManager中有一个typedef,如下所示:

class BookManager
   {
   public:
      typedef std::shared_ptr<BookManager> Ptr;
      ...
   };
Run Code Online (Sandbox Code Playgroud)

这允许我们写这个:

BookManager::Ptr bookManager;
Run Code Online (Sandbox Code Playgroud)

这看起来更像是普通的指针语法,而不是原始的共享指针语法.

有没有人有这两种方法的经验?还有其他建议吗?

Lou*_*nco 7

在C++中,如果您对共同对象进行共享,非协调访问,那么最常见的方法是某种引用计数,您可以从中获得shared_ptr.

唯一的缺点是它在C++(特别是库)中并不普遍,所以有时你需要访问原始指针.在这些情况下,您需要小心保持对象存活.

我建议如果你使用shared_ptr - 尝试在任何地方使用它,除非它是不可能的.是的,如果你愿意,可以使用typedef.