浅谈C++智能指针unique_ptr实现

本文参考boost库实现了unique_ptr大部分函数。另外一篇文章《C++14 智能指针unique_ptr、shared_ptr、weak_ptr》可以对照着看。

unique_ptr指针实现时需要注意几点,具体如下:

  1. 构造函数需要声明为explicit,同时需要有默认的删除器。
  2. 对于左值的拷贝构造和赋值函数都需要声明为delete。
  3. 相反,需要支持右值得拷贝构造和赋值。以支持std::move运算。
  4. [可选] 如果需要支持数组,那么需要对unique_ptr类偏特化。为了简洁明了,本文没有附上,可以在GitHub中自行获取。
  5. [可选] c++14支持了make_unique,本文也实现了。

算法实现,[https://github.com/qingdujun/algorithm/blob/master/unique_ptr.cpp]

namespace std2 {//namespace std2 begin

template<class T>
struct default_delete {
void operator()(T* p) const noexcept {
delete p;
p = nullptr;
}
};

template<typename T, typename D = default_delete<T>>
class unique_ptr {
public:
explicit unique_ptr(T* p, const D& d = D()) noexcept
: ptr_(p, d) {
}
~unique_ptr() {
reset();
}
unique_ptr(const unique_ptr&) = delete;
unique_ptr& operator=(const unique_ptr&) = delete;
unique_ptr(unique_ptr&& rhs) noexcept
: ptr_(rhs.release(), rhs.ptr_.second) {
}
unique_ptr& operator=(unique_ptr&& rhs) noexcept {
if (this != &rhs) {
reset(rhs.release());
}
return *this;
}
T& operator*() const noexcept {
return *ptr_.first;
}
T* operator->() const noexcept {
return ptr_.first;
}
T* release() noexcept {
T* temp_ptr = ptr_.first;
ptr_.first = nullptr;
return temp_ptr;
}
void reset(T* p = nullptr) noexcept {
T* temp_ptr = ptr_.first;
ptr_.first = p;
if (temp_ptr) {
ptr_.second(temp_ptr);
}
}
void swap(T& u) noexcept {
std::swap(ptr_, u);
}
T* get() const noexcept {
return ptr_.first;
}
/**
* operator > < != == , you can see, https://code.woboq.org/appleseed/include/boost/move/unique_ptr.hpp.html#boost::movelib::unique_ptr::pointer_type_obtainer
*/
private:
std::pair<T*, D> ptr_;
};

/**
* Partial specialization of class templates to support T[] types
* You can see, https://github.com/qingdujun/algorithm/blob/master/unique_ptr.cpp
*/
template<typename T, typename... Ts>
std2::unique_ptr<T> make_unique(Ts&&... args) {
return std2::unique_ptr<T>(new T(std::forward<Ts>(args)...));
}

}//namespace std2 end

References:

[1] boost, https://www.boost.org/doc/libs/1_62_0/boost/move/unique_ptr.hpp [2] Senlin's Blog,深入C++的unique_ptr