I know I haven't implemented many methods, and haven't specialized it for T[]
, but I just want to see if what I coded is good or bad.
template< class T >
class unique_ptr
{
private:
T* ptr;
public:
unique_ptr() noexcept : ptr(nullptr) {}
~unique_ptr() noexcept { release(); }
explicit unique_ptr(T* data) noexcept;
unique_ptr(const unique_ptr& rhs) = delete;
unique_ptr& operator=(const unique_ptr& rhs) = delete;
unique_ptr(unique_ptr&& rhs) noexcept;
unique_ptr& operator=(unique_ptr&& rhs) noexcept
{
ptr = std::move(rhs.ptr);
}
T& operator*() { return *get(); }
T* get() const noexcept;
T* release() noexcept;
};
template< class T >
unique_ptr<T>::unique_ptr(T* data) noexcept : ptr(data) {}
template< class T >
unique_ptr<T>::unique_ptr(unique_ptr&& rhs) noexcept
{
ptr = std::move(rhs.ptr);
}
template< class T >
T* unique_ptr<T>::get() const noexcept
{
return ptr;
}
template < class T >
T* unique_ptr<T>::release() noexcept
{
auto old_ptr = ptr;
ptr = nullptr;
return old_ptr;
}
template< typename T, typename ...Args >
unique_ptr<T> make_unique(Args&&... args)
{
return unique_ptr<T>(new T(std::forward<Args>(args)...));
}
1 Answer 1
What's implemented so far looks mostly fine, except for the destructor. I would add operator->()
as soon as possible, since we have operator*()
- they come as a pair, and I don't think it's yet defaultable in the way that !=
can be synthesized when we provide ==
.
Technically, we don't need = delete
declarations of copy-construct/assign, since providing move-construct/assign inhibits those. But I like showing that explicitly - it can help the reader.
We could make the T*
constructor also be the default constructor, by using a default argument:
explicit unique_ptr(T* data = nullptr) noexcept;
operator*
needs to be const
(it can be noexcept
, too).
release()
can be simplified to just return std::exchange(ptr, nullptr);
. It probably should make marked [[nodiscard]]
since it transfers ownership of the pointer.
There's a bug in the destructor: we just call release()
, abandoning the ownership of the pointer. But we actually need to free the owned object instead:
~unique_ptr() noexcept { delete ptr; }
(Remember that delete
on a null pointer is safe, and does nothing).
Explore related questions
See similar questions with these tags.