1

I am currently following the book **Effective Modern C++" and it says

Avoid creating std::shared_ptrs from variables of raw pointer type.

And I am convinced with the explanation so that I, too, agree on that we need to avoid. But there is an exception I encountered.

class Person
{
protected:
    Person();
public:

    static std::shared_ptr<Person> getShared()
    {
        return std::shared_ptr<Person>(new Person());
    }

When we hide the default constructor std::make_shared cannot do its job. That's why I use a static method in the example above. My question is

  1. Is this best I can do about the situation?
  2. I still use raw pointer to create a shared_ptr, but in this case I can predict what may happen to this pointer. Does this practice still threaten my code?
ozgur
  • 2,159
  • 2
  • 17
  • 37
  • Of course you can't create a `std::shared_ptr` object without passing in a raw pointer, what the book says is that you should avoid creating the share pointers from pointer variables. It's right there in the quote even. :) – Some programmer dude Nov 20 '15 at 15:54
  • @JoachimPileborg You are supposed to use `make_shared` to avoid passing a raw pointer. – nwp Nov 20 '15 at 15:56
  • @JoachimPileborg `auto i = make_shared(42);` No raw pointer passed anywhere. Am I missing something? – nwp Nov 20 '15 at 16:00
  • On a related note, you might want to read about [`std::enable_shared_from_this`](http://en.cppreference.com/w/cpp/memory/enable_shared_from_this). – Some programmer dude Nov 20 '15 at 16:00
  • Well obviously I'm not talking about `make_shared`, but the OP in his second question says that a raw pointer is used, and that's true. You can't create a `shared_ptr` object the way the OP is doing without passing a pointer. `make_shared` is nice in that it hides the creation of the pointer. – Some programmer dude Nov 20 '15 at 16:03

1 Answers1

1

Although this might not be the best way to do that, one way to do get your constructor protected to a certain degree but still make it callable by std::make_shared is the following:

class MyClass
{
protected:
    struct ConstructorGuard {};

public:
    MyClass(ConstructorGuard g) {}

    static std::shared_ptr<MyClass> create()
    {
         return std::make_shared<MyClass>(ConstructorGuard());
    }
};

The constructor itself is public, but it cannot be called from outside the class, because it requires an argument of type ConstructorGuard which is a protected nested class, such that only the class itself (and the derived classes) can construct such an object to pass it to the constructor.

nh_
  • 2,141
  • 12
  • 24
  • That is actually an interesting solution. It works, client gets a little confused, though. But I will still accept the answer. – ozgur Nov 20 '15 at 16:03