根据参考创建 shared_ptr

Create shared_ptr from reference

我是 C++ 的新手,这个接缝就像一个菜鸟问题,但我无法通过互联网上的其他资源解决它。

我正在尝试根据参考创建 shared_ptr。我有以下 Book class:

#include <memory>
#include "Author.hpp"

class Book
{
   public:
      void setAuthor(const Author& t_author);

   private:
      std::shared_ptr<Author> m_author;
}

这是我的 Author class:

#include <memory>
class Book;

class Author
{
   public:
      void addBook(const Book& t_book);

   private:
      std::vector<std::weak_ptr<Book>> m_books;
}

我厌倦了像这样实现 Book::setAuthor 方法:

void Book::setAuthor(const Author& t_author)
{
   m_author = std::shared_ptr<Author>(&t_author);
}

但是如果我尝试编译它,我会得到:

Invalide conversion from const Author* to Author*

Invalide conversion from sizeof to const Author

你能告诉我我的代码有什么问题吗?我也对 weak_ptr 进行了同样的尝试,但这也不起作用。

尽管如此,您的错误源于以下事实:正在使用的 std::shared_ptr<Author> 构造函数期望 Author*,但表达式 &t_author 结果为类型 const Author*


另一个错误:

void Book::setAuthor(const Author& t_author)
{
   m_author = std::shared_ptr<Author>(&t_author);
}

想象一下调用 book.setAuthor(Author("Herb Sutter"));,你将有一个 悬空指针 因为 t_author 将在该函数完成后不复存在。


您需要将对象复制或移动到您的 std::shared_ptr 实例中。尽可能使用 std::make_shared<T> 创建您的 std::shared_ptr<T> 对象。

void Book::setAuthor(const Author& t_author)
{
   m_author = std::make_shared<Author>(t_author);
}

更好的是:

void Book::setAuthor(Author t_author)
{
   m_author = std::make_shared<Author>(std::move(t_author));
}

如果你想复制使用std::make_shared:

void Book::setAuthor(const Author& t_author)
{
   m_author = std::make_shared<Author>(t_author);
}

但这是一个错误的设计,如果您希望保留传递对象的所有权,您应该将 std::shared_ptr 传递给您的函数而不是 const 引用:

void Book::setAuthor( std::shared_ptr<Author> t_author)
{
   m_author = std::move( t_author );
}

这可能是未定义的行为。 shared_ptr 表示它指向的对象的 所有权 。在几乎所有可以想象的场景中,t_author 指的是一个现有的 Author,它被其他东西拥有。几乎肯定会有两个地方试图破坏实例。

如果您必须为现有实例创建一个shared_ptr,您可以考虑使用enable_shared_from_this,但这仅在t_author 是用 std::make_shared 创建的。如果是这种情况,您不妨更改函数以直接接受 shared_ptr。或者,您可以使用不执行任何操作的自定义删除器创建 shared_ptr。但在这一点上,使用 shared_ptr 没有任何好处,除了可能与某些接口的兼容性。