Question

While working with std::shared_ptr a lot I kind of miss a shared_ref implementation. That is a specialization of shared_ptr, which guarantees, that it never wraps a nullptr (given right usage, of course). I kind of wonder why it is not in the C++11 standard. Are there any mayor problems when implementing it? On the top of my head I cannot think of any.

EDIT:

I would expect to have an interface similar to:

template <typename T>
class shared_ref {
public:
  shared_ref( T&& ref );
  T& get();
  T* operator&() const;

  template< class Y > 
  void reset( Y&& obj );

  long use_count() const;
  bool unique() const;

  void swap( shared_ref& r );
};
Was it helpful?

Solution

Are there any mayor problems when implementing it?

Here's one: you can't take ownership of a reference. The whole point of a smart pointer is to claim ownership of the pointer itself. shared_ref can't work because you can't control the lifetime of a reference.

And no, this isn't going to fly either:

shared_ref( T&& ref ) : p(&ref) {}

The user may have given you a stack variable, which now means you have "shared" ownership between this object and a stack variable. And stack variables cannot share ownership with something.

You can only control the lifetime of a pointer. And pointers can be NULL. Therefore, the only thing you can do is a runtime check to see if a pointer is NULL.

The absolute best you can do is an interface equivalent to shared_ptr except that it has no default constructor and throws in the event of being given NULL. Is that really worth creating a whole new pointer type over?


The C++ Core Guidelines support library has the not_null template, which can be applied to most pointer-like types. So you can use not_null<shared_ptr> when you want to verify that a pointer isn't NULL, but only once when it enters use. After the initial creating of the pointer, it doesn't need to check again.

Granted, you can't force other people to use them, but use of the type consistently will resolve the issue.

OTHER TIPS

There are only two ways for a shared_ptr to be null - either it was default constructed, or it was assigned a null value at some point. Since you already agree it doesn't make sense to default construct your hypothetical shared_ref class, that leaves only the second condition.

If you tried to assign a nullptr to your shared_ref object, what would you expect to happen? Should it throw an error? It's trivial to do the same thing with a regular shared_ptr using a simple template function:

template<typename T>
T* notnull(T* ptr)
{
    if (ptr == std::nullptr)
        throw std::invalid_argument(std::string("nullptr"));
    return ptr;
}

std::shared_ptr<int> pint = notnull(GetIntPtr());

Generally things aren't added to the standard unless there's a compelling need with no easy workarounds.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top