The shared pointer aliasing constructor (8 on cppreference) takes r
by a constant reference. Is there a reason that value semantics are avoided?
The libcxx implementation of this basically copies the two pointers and increments the reference count if applicable.
shared_ptr(const shared_ptr<_Yp>& __r, element_type *__p) _NOEXCEPT
: __ptr_(__p),
__cntrl_(__r.__cntrl_)
{
if (__cntrl_)
__cntrl_->__add_shared();
}
Is there a reason we cannot rely on the copy constructor to increment the reference count? So something like the following:
template<class _Yp>
shared_ptr(shared_ptr<_Yp> __r, element_type *__p) _NOEXCEPT
: __ptr_(__p),
__cntrl_(__r.__cntrl_) {}
This was, the caller can avoid the atomic reference increment with std::move
. I see c++20 adds an r-value overload that I assume is for this purpose. But why was this chosen over switching to the simpler value semantics and having only one overload.
You are missing the destructor. your suggested implementation will decrement the count upon return from constructor (the automatic shared_ptr
instance will be destructed). So if the compiler is not able to optimize to noop, you just pay the cost of two extra atomic operation for no gain and an added logical error that will backlash with a UB.
Regardless of the devised semantics, the constructor must increment the count. However, your proposed solution -after fixing the bug you've introduced- combines the implementation of both r-value and l-value versions of the constructor in a by-value constructor, discarding the mandatory atomic access optimization imposed by current implementation.