I know that it is to prevent two copies of unique_ptr to have a possible dangling pointer where the pointed-to object could have been already deallocated and stuff like that. But why didn't they decide to allow a kind of deep copy, where instead of just copying pointers they allocate new memory and delegate the copy to the template argument type of unique_ptr.
CodePudding user response:
The main problem is that just blindly calling the template argument's copy ctor with new will slice the object if it is actually a subclass, making this a very unsafe thing to do in general.
That said, I've found it useful to extend unique_ptr:
template<class T, class D = std::default_delete<T>>
class autoclone_ptr : public std::unique_ptr<T, D> {
public:
autoclone_ptr() = default;
autoclone_ptr(autoclone_ptr &&) = default;
autoclone_ptr &operator=(autoclone_ptr &&) = default;
autoclone_ptr(const autoclone_ptr &a) : std::unique_ptr<T,D>(a ? a->clone() : nullptr) {}
autoclone_ptr &operator=(const autoclone_ptr &a) {
auto *t = a.get();
this->reset(t ? t->clone() : nullptr);
return *this; }
};
This can only be instantiated for classes that define a clone()
method to avoid slicing problems.
CodePudding user response:
It would be confusing to implicitly make a deep copy when copying a pointer. By making it neither Copy Constructible nor Copy Assignable you are forced to make a conscious decision.
In order to call the copy constructor you have to use make_unique: Why std::make_unique calls copy constructor. It will copy the old values to new memory.