Reputation: 10417
From cppreference:
In C++11 and C++14 it is valid to construct a
std::shared_ptr<T>
from astd::unique_ptr<T[]>
:std::unique_ptr<int[]> arr(new int[1]); std::shared_ptr<int> ptr(std::move(arr));
Since the
shared_ptr
obtains its deleter (astd::default_delete<T[]>
object) from theunique_ptr
, the array will be correctly deallocated.This is no longer allowed in C++17. Instead the array form
std::shared_ptr<T[]>
should be used.
Why is it not allowed in C++17? What has changed?
Upvotes: 11
Views: 990
Reputation:
Incorrect constraint for shared_ptr construction from unique_ptr
[...]
Based on implementation experience I believe the correct form is:
Remark: This constructor shall not participate in overload resolution unless
Y*
is compatible withT*
andunique_ptr<Y, D>::pointer
is convertible toelement_type*
.The "compatible with" check prevents undesirable conversions from
unique_ptr<T[]>
toshared_ptr<T>
and the "convertible to" check ensures that the result ofunique_ptr<Y, D>::get()
can be stored in theshared_ptr
and returned byshared_ptr<T>::get()
.
In other words, this was intentionally made invalid just because it shouldn't be valid, not simply a side effect of other changes.
Which makes sense to me. shared_ptr<T>
is likely to be read by other programmers as pointing to only one T
object. Requiring programmers to use shared_ptr<T[]>
when they want multiple T
objects leads to more readable code.
Note: this correct form is not in the standard. The rationale, however, is in part a comment on what is in the standard.
Upvotes: 14