web-dev-qa-db-fra.com

Créer shared_ptr à partir de la référence

Je suis relativement nouveau sur C++ et cela semble être une question noob mais je n'ai pas pu le résoudre avec d'autres ressources sur Internet.

J'essaie de créer un shared_ptr à partir d'une référence. J'ai la classe Book suivante:

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

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

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

Et voici ma classe Author:

#include <memory>
class Book;

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

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

J'en ai assez de mettre en œuvre le Book::setAuthor méthode comme ceci:

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

Mais si j'essaye de compiler ceci, j'obtiens:

Conversion invalide de const Author * en Author *

Conversion invalide de sizeof en const Author

Pouvez-vous me dire ce qui ne va pas avec mon code? J'ai également essayé la même chose avec le faiblesse_ptr mais cela ne fonctionne pas non plus.

7
Cilenco

Cependant, votre erreur provient du fait que le constructeur std::shared_ptr<Author> Utilisé attend Author*, Mais l'expression &t_author Résulte en un objet de type const Author*


Une autre mauvaise chose:

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

Imaginez que vous appelez book.setAuthor(Author("Herb Sutter"));, vous aurez un pointeur suspend car t_author Cessera d'exister une fois cette fonction terminée.


Vous devez copier ou déplacer l'objet dans votre instance std::shared_ptr. Utilisez std::make_shared<T> Pour créer vos objets std::shared_ptr<T> Dans la mesure du possible.

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

Mieux encore:

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

Si vous voulez faire une copie, utilisez std::make_shared:

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

mais ceci est une mauvaise conception, si vous prévoyez de conserver la propriété des objets passés, vous devez passer std::shared_ptr à votre fonction au lieu de la référence const:

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

Il s'agit probablement d'un comportement non défini. shared_ptr indique la propriété de l'objet vers lequel il pointe. Dans à peu près tous les scénarios imaginables, t_author fait référence à un Author existant qui appartient à autre chose. Il y aura presque sûrement deux emplacements qui tenteront de détruire l'instance.

Si vous devez créer un shared_ptr à une instance existante, vous pouvez examiner l'utilisation de enable_shared_from_this , mais cela ne fonctionne que si t_author a été créé avec std::make_shared. Et si c'est le cas, vous pourriez aussi bien changer votre fonction pour accepter le shared_ptr directement. Vous pouvez également créer un shared_ptr avec un suppresseur personnalisé qui ne fait rien. Mais à ce stade, il n'y a rien à gagner à utiliser shared_ptr, sauf peut-être la compatibilité avec certaines interfaces.

2
François Andrieux