Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't std::weak_ptr have operator->?

It could be implemented thusly:

  std::shared_ptr<T> operator->() {
      auto shared = lock();
      if(shared == nullptr) {
          throw std::bad_weak_ptr(); // or some other exception
      }
      return shared;
  }

Live Demo

Why did the authors of weak_ptr decide to not have operator->? (They must have thought of it)

I can think of potential reasons but I wonder what the official reason is, if one exists. Potential reasons:

  • Discourage extra increment/decrement of reference count for multiple calls
  • Encourage explicit locking rather than (somewhat hidden) exceptions

If you are confused about the lifetime of the returned shared_ptr, see this paper.

Also, someone asked why would one use a weak_ptr if you expect it to not be expired? Answer: cycles.

like image 710
Taylor Avatar asked Jan 15 '15 18:01

Taylor


People also ask

What is std :: Weak_ptr?

std::weak_ptr is a smart pointer that holds a non-owning ("weak") reference to an object that is managed by std::shared_ptr. It must be converted to std::shared_ptr in order to access the referenced object.

What is the use of Weak_ptr in C++?

By using a weak_ptr , you can create a shared_ptr that joins to an existing set of related instances, but only if the underlying memory resource is still valid. A weak_ptr itself does not participate in the reference counting, and therefore, it cannot prevent the reference count from going to zero.

Is std :: Weak_ptr thread safe?

Note that the control block used by std::weak_ptr and std::shared_ptr is thread-safe: different non-atomic std::weak_ptr objects can be accessed using mutable operations, such as operator= or reset , simultaneously by multiple threads, even when these instances are copies or otherwise share the same control block ...

How is Weak_ptr implemented?

To implement weak_ptr , the "counter" object stores two different counters: The "use count" is the number of shared_ptr instances pointing to the object. The "weak count" is the number of weak_ptr instances pointing to the object, plus one if the "use count" is still > 0.


2 Answers

The original proposal weak_ptr didn't include an overload of operator->.

I haven't looked through the minutes of every meeting since, but have followed what's been discussed, and don't recall a mention of anybody having proposed that it should be added. As such, the "official" reason it's not present is probably largely that nobody's proposed that it be added.

If you want to go back to the very beginning, most of this stems from John Ellis and David Detlef's Safe, Efficient Garbage Collection for C++ paper, from Usenix 1994. That included a weakptr type in its Appendix B. That's somewhat different (weakptr::pointer returns a pointer directly, or a null-pointer if the pointee has already been destroyed), but still didn't use an operator overload to do the job.

Greg Colvin wrote the original proposal to add counted_ptr to the standard. Its counted_ptr was essentially equivalent to what's now called shared_ptr, but did not include anything analogous to weak_ptr.

Shortly after the committee rejected the counted_ptr proposal and adopted auto_ptr instead, the basic idea of counted_ptr was revived on Boost. I don't remember seeing any discussion of adding an operator-> to it, but it "lived" there for so long that it's entirely possible somebody could have proposed it without my being aware of it.

like image 141
Jerry Coffin Avatar answered Sep 20 '22 15:09

Jerry Coffin


I'll take a shot at giving a good reason why this is not a good idea:

One thing is clarity:

ptr->foo();
ptr->bar();

The problem here is that somewhere between the first and second call, ptr might expire, either by a different thread (which would be a race condition) or by a sideeffect of the call to foo.

Another thing is symmetry: When I have a pointer, I expect operators *, -> and an implicit conversion to a boolean value. Some might disagree, but operators * and -> often coincide. I'd be surprised that this isn't the case here.

That said, with C++11, it's just too easy to write:

if (auto p = ptr.lock()) {
    p->foo();
    p->bar();
}

Knowing that ptr is a weak_ptr, the meaning and behaviour of that code is pretty clear.

like image 21
Ulrich Eckhardt Avatar answered Sep 21 '22 15:09

Ulrich Eckhardt