Re: Does std::unique_ptr support self-reset?
Am 12.08.2013 09:18, schrieb Greg Marr:
On Sunday, August 11, 2013 6:10:02 PM UTC-4, Daniel Kr?gler wrote:
At least in VS2010 and 2012, unique_ptr::reset checks for setting
the same pointer and ignores it.
This is indeed a non-conforming C++11 implementation, because
those effects were intentionally changed as of
I guess the libstdc++ implementation is non-conforming too.
void
reset(pointer __p = pointer()) noexcept
{
using std::swap;
swap(std::get<0>(_M_t), __p);
if (__p != pointer())
get_deleter()(__p);
}
Could you please elaborate why this implementation should be
non-conforming? The comparison with pointer() instead of nullptr is
required to be equivalent as of the NullablePointer requirements that
are imposed on 'pointer'. I tend to say that swapping the function
parameter and the old value of the stored pointer old_p is fine, too,
since lvalues of 'pointer' are also required to be swappable (again see
NullablePointer requirements) and according to [swappable.requirements]
p2 we have a "value equivalence" requirement upon the swapped values, so
we can consider the value of __p in the test above equivalent to the
value of old_p.
(though the array specialization matches the standard)
Presumably, but this depends on the decision upon issue
http://cplusplus.github.io/LWG/lwg-active.html#2262
If the resolution will be applied the follow-up assignment
__ptr = pointer();
(where __ptr refers to the stored pointer) is no longer valid after
invocation of the deleter on the interally stored pointer.
http://gcc.gnu.org/viewcvs/gcc/trunk/libstdc%2B%2B-v3/include/bits/unique_pt
r.h?view=markup
I read the defect report, but I still can't understand why someone would
explicitly change from specifying that p.reset(p.get()) was safe to it
resulting in undefined behavior (dangling pointer immediately and then a
double-delete in the unique_ptr destructor), especially for a class whose
entire purpose is to help eliminate memory errors such as dangling
pointers
and double-frees.
Keep in mind, that C++11 was not a completed standard when the original
proposal for std::unique_ptr was made, so a behavioural change does not
exist from the point of the standard, since the issue was accepted
before standard completion. In addition, I also find the example
p.reset(p.get())
very unconvincing, because this is similarly invalid as if you would
provide an "unmanaged" pointer value to two different std::unique_ptr
objects:
int* p_raw = new int(42);
std::unique_ptr p1(p_raw);
std::unique_ptr p2(p_raw);
or a variation of this:
std::unique_ptr p1(p_raw);
std::unique_ptr p2(p1.get());
Note also that the standardized std::unique_ptr::reset behaviour is
similar to that of std::shared_ptr::reset: Here it is more explicitly
said that the effects are equivalent to "shared_ptr(p).swap(*this)", so
the corresponding code
p.reset(p.get())
would be invalid for a std::shared_ptr object p, too. No-one had
interest to change the semantics of std::auto_ptr, because the
difference would have been observable versus C++03 and because
std::auto_ptr is deprecated in C++11. Further-more, std::auto_ptr always
required it's template argument to be a complete type, so the
circular-reference example was never supported (C++11 ensured
incomplete-type support for shared_ptr and unique_ptr).
This is especially puzzling to me when I then read 998,
where the standard was changed to eliminate UB in a case that seems to me
to be even more likely to be a coding error (my bad_idea example above).
It was really intended to support circular references and the existing
wording presumably will be made clearer, see also
http://cplusplus.github.io/LWG/lwg-active.html#2262
HTH & Greetings from Bremen,
- Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]