Date: Mon, 25 Nov 2019 23:07:00 +0000
Thanks both for your responses!
> Have you ever found a case in real code where "change std::shared_ptr to std::weak_ptr" was an appropriate way to fix a reference cycle?
Hmm, I thought I had an example in mind, but it looks like I misremembered it - the example I was thinking of was actually changing uses of raw pointers to std::weak_ptrs. This change would still be useful to reduce code churn in this situation.
> weak_ptr, despite its name, is not a pointer
> and doesn't behave like a pointer, so in that
> sense the value of the added symmetry seems potentially negative.
> A weak_ptr is not itself any kind of pointer; you can't dereference a weak_ptr. Think of a weak_ptr as a "ticket for a shared_ptr." (I strongly recommend watching my CppCon 2019 talk "Back to Basics: Smart Pointers".) Since a weak_ptr isn't a pointer, it has no natural "null pointer" state. It does have an "expired" state (and, orthogonally, the controlled pointer might be null or non-null).
Interesting, I hadn’t considered weak_ptrs in that way. Intuitively, I guess I’ve always considered them as pointer-like reference types, even if they cannot be directly dereferenced.
I would consider weak_ptrs that are ‘expired’ and those that are explicitly assigned to nullptr (via a shared_ptr, for sake of argument) to both be null (as, FWIW, lock() will return nullptr in both cases). If I get what you’re saying, I think the contention here is down to whether such a null state qualifies as a ’null pointer’ state.
> There is no reason for "nullptr" to construct an expired std::weak_ptr, any more than "nullptr" should construct an empty std::optional.
(Honestly, this makes me wonder why nullptr can construct an empty std::function, but it’s probably best not to go down that rabbit hole.)
While, based on its lack of a dereference operator, weak_ptr is not a pointer, it is practically used in very similar ways to pointers (both raw and shared) - just with different ownership semantics, and a lock() function that must be called before it may be dereferenced.
Due to this practical similarity (in addition to weak_ptr’s overall symmetry with shared_ptr), I see no issue with nullptr being used to construct a weak_ptr. I can appreciate the concern that this might exacerbate any perception that weak_ptr is a pointer type, but if there was a genuine concern about this, it should probably have been named more carefully...
In any case, I can see why this ‘weak_ptr is not a pointer’ mentality would have led to this implicit constructor not being added in the first place, so thanks for answering that question. That said, I still feel that this would be a convenient addition.
-Ben
> Have you ever found a case in real code where "change std::shared_ptr to std::weak_ptr" was an appropriate way to fix a reference cycle?
Hmm, I thought I had an example in mind, but it looks like I misremembered it - the example I was thinking of was actually changing uses of raw pointers to std::weak_ptrs. This change would still be useful to reduce code churn in this situation.
> weak_ptr, despite its name, is not a pointer
> and doesn't behave like a pointer, so in that
> sense the value of the added symmetry seems potentially negative.
> A weak_ptr is not itself any kind of pointer; you can't dereference a weak_ptr. Think of a weak_ptr as a "ticket for a shared_ptr." (I strongly recommend watching my CppCon 2019 talk "Back to Basics: Smart Pointers".) Since a weak_ptr isn't a pointer, it has no natural "null pointer" state. It does have an "expired" state (and, orthogonally, the controlled pointer might be null or non-null).
Interesting, I hadn’t considered weak_ptrs in that way. Intuitively, I guess I’ve always considered them as pointer-like reference types, even if they cannot be directly dereferenced.
I would consider weak_ptrs that are ‘expired’ and those that are explicitly assigned to nullptr (via a shared_ptr, for sake of argument) to both be null (as, FWIW, lock() will return nullptr in both cases). If I get what you’re saying, I think the contention here is down to whether such a null state qualifies as a ’null pointer’ state.
> There is no reason for "nullptr" to construct an expired std::weak_ptr, any more than "nullptr" should construct an empty std::optional.
(Honestly, this makes me wonder why nullptr can construct an empty std::function, but it’s probably best not to go down that rabbit hole.)
While, based on its lack of a dereference operator, weak_ptr is not a pointer, it is practically used in very similar ways to pointers (both raw and shared) - just with different ownership semantics, and a lock() function that must be called before it may be dereferenced.
Due to this practical similarity (in addition to weak_ptr’s overall symmetry with shared_ptr), I see no issue with nullptr being used to construct a weak_ptr. I can appreciate the concern that this might exacerbate any perception that weak_ptr is a pointer type, but if there was a genuine concern about this, it should probably have been named more carefully...
In any case, I can see why this ‘weak_ptr is not a pointer’ mentality would have led to this implicit constructor not being added in the first place, so thanks for answering that question. That said, I still feel that this would be a convenient addition.
-Ben
Received on 2019-11-25 17:09:24