6

Proposal N4282 advocates a new type of non-owning smart pointer called an observer_ptr. Its working name was exempt_ptr and it's intended as a replacement for "raw pointers". But I don't understand its purpose, especially with this hypothetical code for what it's designed to achieve:

struct do_nothing
{
  template <class T>
  void operator ()(T*) { }; // do nothing
};

template <class T>
  using non_owning_ptr = unique_ptr<T, do_nothing>;

Even after reading the article, I don't understand the purpose of a smart pointer that doesn't do nothing. What advantage does it have over a non-owning shared_ptr or raw pointer?

user6262916
  • 198
  • 3
  • 3
    It helps you write correct code via static analysis. For instance, if you mistakenly call `delete` on one of them, the compiler will give you an error, preventing you from freeing memory you don't own. – Rob K Apr 27 '16 at 17:55

1 Answers1

7

Did you read the "Motivation" section from proposal N4282 that you linked?

It has often proven to be very challenging and time-consuming for a programmer to inspect code in order to discern the use to which any specific bare pointer is put, even if that use has no management role at all. As Loïc A. Joly observed, “it is not easy to disambiguate a T* pointer that is only observing the data.... Even if it would just serve for documentation, having a dedicated type would have some value I think.” Our experience leads us to agree with this assessment.

In other words, it's to make code more self-documenting.

For example, if I see the following function:

void do_something(Foo *foo);

then I don't know if do_something is taking ownership of foo, wants a Foo array of indeterminate length, just needs a nullable reference to it, is using it as a Google C++ Style Guide style output parameter, or is legacy C-style code that just wants a reference.

However, if I see

void do_something(observer_ptr<Foo> foo);

then I know it's observing a Foo instance, and no more.

The C++ Core Guidelines have several additional examples (owner, not_null, etc.) of using templates, not to add run-time functionality, but to better document behavior.

Josh Kelley
  • 56,064
  • 19
  • 146
  • 246
  • Does observer_ptr prevent writing to the wrapped ptr? Also, the motivating issue you're presenting in your answer can be solved by a Foo const * ptr. What does an observer_ptr provide that a const ptr doesn't? Just interested in your take on this. –  May 16 '16 at 11:01
  • 1
    @denniskb - It's not that `observer_ptr` can do anything that `Foo const *ptr` can't. (That's why it's called "the world's dumbest smart pointer.") It's that an `observer_ptr` can _better communicate to other developers_ (and, potentially, to static analysis tools) how the pointer is used. – Josh Kelley May 16 '16 at 12:23
  • thx for the clarification. I strongly disagree with this statement though. const was made for this, it is one of the strongest guarantees you can provide in a C++ program. I don't see the benefit of adding new, redundant syntax with weaker semantics, when const correctness has been practiced by devs for decades now. –  May 16 '16 at 16:11
  • 1
    @denniskb - `observer_ptr` isn't new syntax; it's a new library feature. It's not redundant with `const`; as I explained, it's intended to communicate meaning where a raw `Foo const *` can be ambiguous (observer versus sink versus array versus optional reference). It's not "weaker" than const, it's simply different; e.g., there's nothing stopping you from using `observer_ptr`. – Josh Kelley May 16 '16 at 16:50