微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c++ 智能指针unique_ptr 详解

定义

对于智能指针unique_ptr有两种定义方式

第一种,管理单个对象(使用new分配),并使用认的删除器。
template<
    class T,
    class Deleter = std::default_delete<T>
> class unique_ptr;

第二种则是管理对象数组(使用new[] 分配),并且需要用户指定删除器。Deleter 必须是函数对象
template <
    class T,
    class Deleter
> class unique_ptr<T[], Deleter>;

对于unique_ptr 满足可移动构造,可移动赋值,可复制赋值与可赋值构造则定义为删除形式。
unique_ptr(const unique_ptr&) = delete;
unique_ptr& operator=(const unique_ptr&) = delete;

描述

一个unique_ptr能将所有权给另一个unique_ptr,不能将const的unique_ptr给另一个unique_ptr.

unique_ptr可以保存到vector容器中。

关于继承,若 T 是某基类 B 的派生类,则 std::unique_ptr<T> 可隐式转换为 std::unique_ptr<B>。产生的 std::unique_ptr<B> 的删除器将使用 基类B 的 opterator delete ,因此会出现未定义行为错误,除非 B 的析构函数为虚函数

std::shared_ptr不会出现此问题。std::shared_ptr<B> 将使用类型 T 的 派生类的opterator delete 函数 ,而且即使 基类B 的析构函数非虚函数,也会正确删除对象。

关联的函数

1.构造函数

构造函数有很多种,只列举移动构造,但是赋值构造认是删除的。

    unique_ptr(unique_ptr&& __u) noexcept
      : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }

2.析构函数

 ~unique_ptr()
      {
	auto& __ptr = _M_t._M_ptr();
	if (__ptr != nullptr)
	  get_deleter()(__ptr);
	__ptr = pointer();
      }

3.赋值函数

所谓的赋值函数是可移动赋值函数,不是拷贝赋值函数,
 unique_ptr&
      operator=(unique_ptr&& __u) noexcept
      {
	reset(__u.release());
	get_deleter() = std::forward<deleter_type>(__u.get_deleter());
	return *this;
      }

4.release函数

释放存储的指针,但不释放指针指向的对象,返回释放的指针。
如果调用release后没有接收此指针,则数据指向的数据将不会被释放。
 pointer
      release() noexcept
      {
	pointer __p = get();
	_M_t._M_ptr() = pointer();
	return __p;
      }

5.reset函数

重新接收新的指针,如果当前指针和传入指针不是同一个,则调用删除器释放当前指针指向的数据 。
保留的是传入的新指针。
 reset(pointer __p = pointer()) noexcept
      {
	using std::swap;
	swap(_M_t._M_ptr(), __p);
	if (__p != pointer())
	  get_deleter()(__p);
      }

6.swap函数

使用std::swap函数
void
      swap(unique_ptr& __u) noexcept
      {
	using std::swap;
	swap(_M_t, __u._M_t);
      }

7.get函数

返回存储的指针
 pointer
      get() const noexcept
      { return _M_t._M_ptr(); }

8.get_deleter函数

返回对象对应的删除器
 deleter_type&
      get_deleter() noexcept
      { return _M_t._M_deleter(); }

_M_t是tuple类型。

_Dp&       _M_deleter() { return std::get<1>(_M_t); }
取tuple的第二个元素,也就是std::get<1>(tuple);

9.opterator bool 函数

返回当前存储的指针是不是空,是空的话返回false, 非空返回ture
explicit operator bool() const noexcept
      { return get() == pointer() ? false : true; }

10.opterator *函数

对存储的指针进行解引用操作
typename add_lvalue_reference<element_type>::type
      operator*() const
      {
	__glibcxx_assert(get() != pointer());
	return *get();
      }

11.opterator ->函数

返回存储的对象指针。
pointer
      operator->() const noexcept
      {
	_GLIBCXX_DEBUG_PEDASSERT(get() != pointer());
	return get();
      }

12.opterator []函数,访问数组成员。

主要实现:
typename std::add_lvalue_reference<element_type>::type
      operator[](size_t __i) const
      {
	        __glibcxx_assert(get() != pointer());
	        return get()[__i];
      }
get()函数会返回当前数组的指针。

pointer  get() const noexcept      { return _M_t._M_ptr(); }
_M_t的类型时std::tuple类型,tuple中第一个元素是对象指针,第二个对象是删除器。

pointer    _M_ptr() const { return std::get<0>(_M_t); }
_M_ptr()是取tuple中的第一个元素,对象指针。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐