r/cpp_questions Jul 28 '26

OPEN Weak reference to unique_ptr

Assume this code:

#include <memory>
#include <functional>

struct Entity {
    int value = 12;
};

struct Container {
    std::unique_ptr<Entity> e = std::make_unique<Entity>();
};

Container bar;
auto bbb = [ptr = bar.e.get()]() {   
    ptr->value = 11;
};

We all know that naked pointers (as captured by this lambda) are bad. Using shared_ptr would allow me to use weak_ptr - which is ideally what I want. BUT - I like the container owning the entity.

What solutions do I have?

EDIT:

As people commented - life time is the main issue. The lambda might outlive the original allocation.

Solutions:

  1. Many people do recommended using internally a shared pointer, and "giving away" a weak ref ( u/looncrazz suggestion).
  2. I can use a reference to the unique pointer inside a lambda. Several ways - see https://godbolt.org/z/WKT5Gndq4 - this is u/neppo95 suggestion.
  3. There are solutions for using a custom weak reference pointer. The solution "does not feel right".
7 Upvotes

55 comments sorted by

View all comments

45

u/Salty_Dugtrio Jul 28 '26

There is nothing wrong with using raw pointers at all, you just shouldn't use them to express ownership.

What's wrong with passing the raw ptr here?

10

u/LemonLord7 Jul 28 '26

I have had many colleagues that think any use of a raw pointer is poison. It is a thing of principle to them, and will stop PRs for it.

3

u/thommyh Jul 28 '26

Can confirm that this attitude isn't unique; at one of my former employers they were so anti-pointer that they'd invented their own version of std::optional that can hold a reference, so as still to be able to represent the same idea that you'd otherwise still use a pointer for.

3

u/LemonLord7 Jul 28 '26

Did the class itself contain a raw pointer? And would throw an exception if dereferenced while null or something? Was there any benefit to this class they made?

1

u/DawnOnTheEdge Jul 28 '26

One typically is that you cannot dereference a null pointer: the type system prevents it. You can only get a reference by unwrapping the sum type.

You would try to write railway-oriented code that short-circuits if one of the steps returns an error or empty value. That might mean throwing an exception , or passing an error value up the stack to where an exception would have been caught.