I was reading Top 10 dumb mistakes to avoid with C++11 smart pointer. Number #5 reads:
Mistake # 5 : Not assigning an object(raw pointer) to a shared_ptr as soon as it is created !
int main()
{
Aircraft* myAircraft = new Aircraft("F-16");
shared_ptr<aircraft> pAircraft(myAircraft);
...
shared_ptr<aircraft> p2(myAircraft);
// will do a double delete and possibly crash
}
and the recommendation is something like:
Use
make_shared
ornew
and immediately construct the pointer with it.
Ok, no doubt about it the problem and the recommendation.
However I have a question about the design of shared_ptr
.
This is a very easy mistake to make and the whole "safe" design of shared_ptr
could be thrown away by very easy-to-detect missuses.
Now the question is, could this be easily been fixed with an alternative design of shared_ptr
in which the only constructor from raw pointer would be that from a r-value reference?
template<class T>
struct shared_ptr{
shared_ptr(T*&& t){...basically current implementation...}
shared_ptr(T* t) = delete; // this is to...
shared_ptr(T* const& t) = delete; // ... illustrate the point.
shared_ptr(T*& t) = delete;
...
};
In this way shared_ptr
could be only initialized from the result of new
or some factory function.
Is this an underexploitation of the C++ language in the library? or What is the point of having a constructor from raw pointer (l-value) reference if this is going to be most likely a misuse?
Is this a historical accident? (e.g. shared_ptr was proposed before r-value references were introduced, etc) Backwards compatibility?
(Of course one could say std::shared_ptr<type>(std::move(ptr));
that that is easier to catch and also a work around if this is really necessary.)
Am I missing something?