This page is a snapshot from the LWG issues list, see theLibrary Active Issues List for more information and the meaning ofCD1 status.
unique_ptr::reset effects incorrect, too permissiveSection: 20.3.1.3.6[unique.ptr.single.modifiers]Status:CD1Submitter: Peter DimovOpened: 2008-03-13Last modified: 2016-01-28
Priority:Not Prioritized
View all otherissues in [unique.ptr.single.modifiers].
View all issues withCD1 status.
Discussion:
void unique_ptr::reset(T* p = 0) is currently specified as:
Effects: If
p == get()there are no effects. Otherwiseget_deleter()(get()).
There are two problems with this. One, ifget() == 0 andp != 0, thedeleter is called with aNULL pointer, and this is probably not what'sintended (the destructor avoids calling the deleter with 0.)
Two, the special check forget() == p is generally not needed and such asituation usually indicates an error in the client code, which is beingmasked. As a data point,boost::shared_ptr was changed to assert on suchself-resets in 2001 and there were no complaints.
One might think that self-resets are necessary foroperator= to work; it's specified to perform
reset( u.release() );
and the self-assignment
p = move(p);
might appear to result in a self-reset. But it doesn't; therelease() isperformed first, zeroing the stored pointer. In other words,p.reset(q.release() ) works even whenp andq are the sameunique_ptr, and thereis no need to special-casep.reset( q.get() ) to work in a similarscenario, as it definitely doesn't whenp andq are separate.
Proposed resolution:
Change 20.3.1.3.6[unique.ptr.single.modifiers]:
void reset(T* p = 0);-4-Effects: If
there are no effects. Otherwisep ==get() == 0get_deleter()(get()).
Change 20.3.1.4.5[unique.ptr.runtime.modifiers]:
void reset(T* p = 0);...
-2-Effects: If
there are no effects. Otherwisep ==get() == 0get_deleter()(get()).