可以将共享指针与非指针数据成员混合使用吗?

发布于 2024-10-06 02:36:08 字数 1438 浏览 3 评论 0原文

采取以下示例:

class BookManager
   {
   ...
   };

class Book
   {
   public:
      void setBookManager(BookManager *bookManager) {m_bookManager = bookManager;}
   private:
      BookManager *m_bookManager;
   };

由于调用者通常不会在删除图书时保留该图书的 BookManager,并且由于多个图书可以共享 BookManager,因此我将指针指向 BookManager,这是一个共享指针,如下所示

typedef std::shared_ptr<BookManager> BookManagerPtr;

class Book
   {
   public:
      void setBookManager(BookManagerPtr bookManager) {m_bookManager = bookManager;}
   private:
      BookManagerPtr m_bookManager;
   };

:我的应用程序中的一个模块有它自己的 BookManager,它想要给它的每本书,如下所示:

class MyModule
   {
   public:
      Book *createBook()
         {
         Book *newBook = new Book();
         newBook->setBookManager(BookManagerPtr(&m_bookManager));
         }
   private:
      BookManager m_bookManager;
   };

当然这不起作用,因为最后删除的书也会删除 BookManager 实例,它不应该删除,因为它是 MyModule 的普通数据成员。

这意味着 MyModule 还应该使用指向 BookManager 的共享指针,如下所示:

class MyModule
   {
   public:
      MyModule()
      : m_bookManager(new BookManager())
         {
         }
      Book *createBook()
         {
         Book *newBook = new Book();
         newBook->setBookManager(m_bookManager);
         }
   private:
      BookManagerPtr m_bookManager;
   };

这是解决此问题的唯一方法吗? 或者有没有办法仍然拥有普通数据成员并使用指向它的共享指针(例如通过将其引用计数初始化为1)?

Take the following example:

class BookManager
   {
   ...
   };

class Book
   {
   public:
      void setBookManager(BookManager *bookManager) {m_bookManager = bookManager;}
   private:
      BookManager *m_bookManager;
   };

Since the caller is typically not interested in keeping a BookManager for a Book if the Book is deleted, and since multiple Books can share a BookManager, I make the pointer to BookManager, a shared pointer, like this:

typedef std::shared_ptr<BookManager> BookManagerPtr;

class Book
   {
   public:
      void setBookManager(BookManagerPtr bookManager) {m_bookManager = bookManager;}
   private:
      BookManagerPtr m_bookManager;
   };

Problem is that a module in my application has its own BookManager that it wants to give to each of its books, like this:

class MyModule
   {
   public:
      Book *createBook()
         {
         Book *newBook = new Book();
         newBook->setBookManager(BookManagerPtr(&m_bookManager));
         }
   private:
      BookManager m_bookManager;
   };

Of course this doesn't work because the last deleted book will also delete the BookManager instance, which it shouldn't delete because it's a normal data member of MyModule.

This means that MyModule should also use a shared pointer to BookManager, like this:

class MyModule
   {
   public:
      MyModule()
      : m_bookManager(new BookManager())
         {
         }
      Book *createBook()
         {
         Book *newBook = new Book();
         newBook->setBookManager(m_bookManager);
         }
   private:
      BookManagerPtr m_bookManager;
   };

Is this the only way to solve this?
Or is there a way to still have normal data members and use shared pointers to it (e.g. by initializing its reference count to 1)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

惜醉颜 2024-10-13 02:36:08

创建一个副本 BookManagerPtr(new BookMarkManager(m_bookManager)) ,使 m_bookManager 也成为 BookManagerPtr 或使 book 成为模板,从而允许它使用 BookManager* 和 shared_ptr。
shared_ptr 是关于共享所有权的,在您的示例中,MyModule 拥有该示例,而本书则没有,因此它与 shared_ptr 不兼容

create a copy BookManagerPtr(new BookMarkManager(m_bookManager)), make m_bookManager a BookManagerPtr too or make book a template thus allowing it to use BookManager* and shared_ptr.
shared_ptr is about shared ownership, in your example MyModule owns the example and book don't, so it's not compatible with shared_ptr

嗳卜坏 2024-10-13 02:36:08

使用不执行任何操作的自定义删除器怎么样?

What about using custom deleter which does nothing?

一个人的夜不怕黑 2024-10-13 02:36:08

我知道您已经接受了答案,但另一种方法(如果您有提升)可能是使用参考文献。默认情况下,您不能在 Book 类中拥有引用成员,但是如果您将其包装在可选的即 boost::optional 中,那么您可以有了一个引用,接下来,在 setBookManager 方法中,传入该引用(或 const 引用)并将其分配给可选值。要使用,请像使用智能指针一样取消引用......

I know you've accepted an answer, but another approach (if you have boost) could be to use references. By default you can't have a reference member in the Book class, however if you wrap it in an optional i.e. boost::optional<BookManager&> then you can have a reference, next, in the setBookManager method, pass in the reference (or const reference) and assign this to the optional. To use, deref as you would a smart pointer...

一城柳絮吹成雪 2024-10-13 02:36:08

对非所有权进行建模的安全方法是使用 weak_ptr,这样生命周期仍然由 MyModule 控制,同时仍然让 Book 引用 >BookManager 并了解它引用的 BookManager 是否仍然有效。

The safe way to model non-ownership is with a weak_ptr this way the lifetime is still controlled by MyModule while still having Book reference a BookManager and know if the BookManager it references is still valid.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文