AutoPtr: do 'duplicate' before 'release' (#4068)

Common knowledge in reference counting is "on assignment increment first
then decrement", because "just to be deleted" object could hold last
reference to "just to be assigned" one.

Fixes #3979
This commit is contained in:
Sokolov Yura 2023-11-23 06:49:10 +03:00 committed by GitHub
parent b34801f4ba
commit 904075e1f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -110,34 +110,23 @@ public:
{ {
if (_ptr != ptr) if (_ptr != ptr)
{ {
if (_ptr) _ptr->release(); if (shared && ptr) ptr->duplicate();
_ptr = ptr; std::swap(_ptr, ptr);
if (shared && _ptr) _ptr->duplicate(); if (ptr) ptr->release();
} }
return *this; return *this;
} }
AutoPtr& assign(const AutoPtr& ptr) AutoPtr& assign(const AutoPtr& ptr)
{ {
if (&ptr != this) return assign(ptr._ptr, true);
{
if (_ptr) _ptr->release();
_ptr = ptr._ptr;
if (_ptr) _ptr->duplicate();
}
return *this;
} }
template <class Other> template <class Other>
AutoPtr& assign(const AutoPtr<Other>& ptr) AutoPtr& assign(const AutoPtr<Other>& ptr)
{ {
if (ptr.get() != _ptr) C* nptr = const_cast<Other*>(ptr.get());
{ return assign(nptr, true);
if (_ptr) _ptr->release();
_ptr = const_cast<Other*>(ptr.get());
if (_ptr) _ptr->duplicate();
}
return *this;
} }
void reset() void reset()