Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create shared_ptr from reference

Tags:

c++

shared-ptr

I'm relativly new to C++ and this seams like a noob question but I wasn't able to solve it with other resources on the internet.

I'm trying to create a shared_ptr from a reference. I have following Book class:

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

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

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

And this is my Author class:

#include <memory>
class Book;

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

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

I tired to implement the Book::setAuthor method like so:

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

But if I try to compile this I get:

Invalide conversion from const Author* to Author*

Invalide conversion from sizeof to const Author

Can you please tell me what is wrong with my code? I also tried the same with the weak_ptr but this does not work either.

like image 930
Cilenco Avatar asked Feb 08 '17 19:02

Cilenco


2 Answers

Though, your error stems from the fact that the std::shared_ptr<Author> constructor in use expects Author*, but the expression &t_author results to an object of type const Author*


Another wrong thing:

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

Imagine calling book.setAuthor(Author("Herb Sutter"));, you will have a dangling pointer because t_author will cease to exist after that function completes.


You need to copy or move the object into your std::shared_ptr instance. Use std::make_shared<T> to create your std::shared_ptr<T> objects whenever possible.

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

Better still:

void Book::setAuthor(Author t_author)
{
   m_author = std::make_shared<Author>(std::move(t_author));
}
like image 106
WhiZTiM Avatar answered Oct 08 '22 13:10

WhiZTiM


If you want to make a copy use std::make_shared:

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

but this is a wrong design, if you expect to keep ownership of passed objects you should pass std::shared_ptr to your function instead of const reference:

void Book::setAuthor( std::shared_ptr<Author> t_author)
{
   m_author = std::move( t_author );
}
like image 23
Slava Avatar answered Oct 08 '22 13:10

Slava