为什么需要智能指针:
因为动态开辟的内存过早,过晚释放都不好,不是放,就会导致内存泄漏------内存被占用,导致无法使用。
智能指针------自动释放所指对象。
智能指针的本质
模板
建立一个类把指针封装起来
智能指针实现原理
简单实现,也容易看懂---链接
智能指针使用的是浅拷贝
当引用计算为0时,需要释放至少两个对象:1,引用计数 2,指针所指对象。
unique_ptr:
一个unique_ptr智能指针独享一个指针对象的所有权,当这个智能指针被赋值时,对象的所有权转移,当智能指针被销毁时,智能指针指向的对象也会被销毁。
可独享的原理:
独享,不可复制:
禁用拷贝构造函数和=重载运算符。
unique_ptr(const unique_ptr<T>&) noexcept = delete;
unique_ptr& operator = (const unique_ptr&) noexcept = delete;
把两种赋值函数,都设置为delete。
使用"=delete"修饰,表示函数被定义为deleted,也就意味着这个成员函数不能再被调用,否则编译就会出错。
以下是不允许的:
为什么可以用=来实现初始化
unique_ptr<int> inst1=unique_ptr<int>(new int);
右边的对象(包括noew出来的对象)为右值,调用的是移动拷贝构造函数。
可转移-move
不可以拷贝,但是可以转移指针对象的所有权,利用了移动拷贝构造函数和参数为右值引用的的=重载函数,所以需要转移所有权的时候需要使用move函数将原来的智能指针转为右值引用,传入到新的智能指针中进行转移。
unique_ptr(unique_ptr&& move) noexcept
{
std::cout << "construct for unique_ptr&&" << std::endl;
move.swap(*this);
}
unique_ptr& operator=(unique_ptr&& move) noexcept
{
move.swap(*this);
return *this;
}
// swaps the resources 将右值引用指向的对象转移给自己
void swap(unique_ptr<T>& resource_ptr) noexcept
{
std::swap(ptr_resource, resource_ptr.ptr_resource);
}
以下是允许的:
unique_ptr<Test> tPtr1(new Test());
//以下两句话就允许,因为pPtr1做了控制权转移
unique_ptr<Test> tPtr3(std::move(tPtr1));
unique_ptr<Test> tPtr4 = std::move(tPtr3);
怎么去除unique_ptr使用
使用unique_ptr的指针或者引用:
std::unique_ptr<Request>& send_request=queue_.front();
不要尝试去除unique_ptr赋给另一个:
shared_ptr:
浅拷贝
不能使用原始指针创建不同的共享指针
make_shared<>()
注意:make_shared不需要再new了,()是用来传输构造函数需要的参数的
shared_ptr初始化
weak_ptr--弱智能指针
1,需要共享智能指针初始化
2,使用通过lock函数检测,指向对象存在则返回一个共享智能指针,使用这个共享智能指针。
3,已经有shared_ptr,为什么还要weak_ptr----连接
(1)用来观察shared_ptr智能指针对象,比如通过弱智能指针的lock或者expird函数可以判断shared_ptr对象是否还存在,通过use_count()判断共享智能指针的引用计数。
(2)最重要的是弱智能指针可以解决共享指针出现的引用计数增加的问题,有时候我们只需要获取对象,不需要增加对象的引用计数时,就需要使用弱智能指针。
(3)和共享指针一起用来解决原始指针循环引用出现的释放内存奔溃的现象和共享指针循环引用出现的无法释放内存的现象。
原始指针循环引用----本来只想释放一个对象的内存,但是却因为相互引用,导致同时想要销毁另一个对象内存,出现奔溃。
共享指针循环引用---开辟的外部对象可以释放,但是内部成员对象没有释放,引用计数还是1,释放不了成员对象,开辟的内存还在。
智能指针比较
指针 | unique_ptr | shared_ptr | weak_ptr |
功能 | 一个指针独享一个对象 | 共享对象 | 借用共享智能指针对象, |
引用计数 | 1 | 增加 | 不改变shared_ptr的引用计数 |
初始化 | unique_ptr<string> up(new string("yuvcsdc")); //unique_ptr不支持拷贝 | 1, shared_ptr<string> sp(new string("yuvcsdc")); 2, auto p=make_shared<int>(100); 拷贝:shared_ptr<int> pp(p); | 建立时需要用共享智能指针来初始化它: auto p=make_shared<int>(42); weak_ptr<int> wp(p); |
调用 | 对象可能不存在,先成员函数lock判断,lock返回一个shared_ptr对象 |
智能指针初始化
智能指针是指针,不能直接利用数据赋值,要利用指针(地址)赋值
shared_ptr<int> p(100);//错
shared_ptr<int> p(new int(100));//对
智能指针的引用计数怎么实现的(计数器存放在哪)
建立另一个类对象来作为计数器,统计引用计数。通过浅拷贝的方式来获取引用计数对象的地址,然后修改这计数器的值。
智能指针函数
unique_ptr
shared_ptr
use_count()-----计算引用计数
源码
unique_ptr
template <typename _Tp, typename _Dp = default_delete<_Tp> >
class unique_ptr
{
class _Pointer
{
template<typename _Up>
static typename _Up::pointer __test(typename _Up::pointer*);
template<typename _Up>
static _Tp* __test(...);
typedef typename remove_reference<_Dp>::type _Del;
public:
typedef decltype(__test<_Del>(0)) type;
};
typedef std::tuple<typename _Pointer::type, _Dp> __tuple_type;
__tuple_type _M_t;
public:
typedef typename _Pointer::type pointer;
typedef _Tp element_type;
typedef _Dp deleter_type;
constexpr unique_ptr() noexcept
:_M_t()
{ static_assert(!is_pointer<deleter_type>::value, "constructed with null function pointer deleter"); }
explicit unique_ptr(pointer __p) noexcept
:_M_t(__p, deleter_type())
{ static_assert(!is_pointer<deleter_type>::value, "constructed with null function pointer deleter"); }
unique_ptr(pointer __p, typename conditional<is_reference<deleter_type>::value, deleter_type, const deleter_type&>::type __d) noexcept
:_M_t(__p, __d)
{
}
unique_ptr(pointer __p, typename remove_reference<deleter_type>::type&& __d) noexcept
:_M_t(std::move(__p), std::move(__d))
{ static_assert(!std::is_reference<deleter_type>::value, "rvalue deleter bound to reference"); }
constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { }
unique_ptr(unique_ptr&& __u) noexcept
:_M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter()))
{
}
template<typename _Up, typename _Ep, typename = _Require<is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>, __not_<is_array<_Up>>, typename conditional<is_reference<_Dp>::value, is_same<_Ep, _Dp>, is_convertible<_Ep, _Dp>>::type>>
unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
:_M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
{
}
~unique_ptr() noexcept
{
auto& __ptr = std::get<0>(_M_t);
if (__ptr != nullptr)
get_deleter()(__ptr);
__ptr = pointer();
}
unique_ptr& operator=(unique_ptr&& __u) noexcept
{
reset(__u.release());
get_deleter() = std::forward<deleter_type>(__u.get_deleter());
return *this;
}
template<typename _Up, typename _Ep>
typename enable_if< __and_<is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>, __not_<is_array<_Up>>>::value, unique_ptr&>::type
operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
{
reset(__u.release());
get_deleter() = std::forward<_Ep>(__u.get_deleter());
return *this;
}
unique_ptr& operator=(nullptr_t) noexcept
{
reset();
return *this;
}
typename add_lvalue_reference<element_type>::type
operator*() const
{
_GLIBCXX_DEBUG_ASSERT(get() != pointer());
return *get();
}
pointer operator->() const noexcept
{
_GLIBCXX_DEBUG_ASSERT(get() != pointer());
return get();
}
pointer get() const noexcept
{ return std::get<0>(_M_t); }
deleter_type& get_deleter() noexcept
{ return std::get<1>(_M_t); }
const deleter_type& get_deleter() const noexcept
{ return std::get<1>(_M_t); }
explicit operator bool() const noexcept
{ return get() == pointer() ? false : true; }
pointer release() noexcept
{
pointer __p = get();
std::get<0>(_M_t) = pointer();
return __p;
}
void reset(pointer __p = pointer()) noexcept
{
using std::swap;
swap(std::get<0>(_M_t), __p);
if (__p != pointer())
get_deleter()(__p);
}
void swap(unique_ptr& __u) noexcept
{
using std::swap;
swap(_M_t, __u._M_t);
}
unique_ptr(const unique_ptr&) = delete;
unique_ptr& operator=(const unique_ptr&) = delete;
};
简单实现
shared_ptr:
#pragma once
#include <iostream>
#include <memory>
using namespace std;
class counter
{
int n;
};
template<typename T>
class sharePtr
{
public:
//初始化的构造函数
sharePtr(T* p) :m_ptr(p)
{
m_count = new counter;
if (p)
m_count->n = 1;
}
//浅拷贝的构造函数
sharePtr(sharePtr<T> const& sp)
{
m_ptr = sp.m_ptr;
m_count = sp.m_count;
(m_count->n)++;
}
//析构函数
~sharePtr()
{
release();
}
//拷贝弱指针对象的构造函数
sharePtr(weak_ptr<T>const& wp)
{
m_ptr = wp.m_ptr;
m_count->n= wp.use_count();
(m_count->n)++;
}
//=重载
sharePtr<T>& operator=(sharePtr<T> const& sp)
{
if (*this != sp)
{
release();
m_ptr = sp.m_ptr;
m_count = sp.m_count;
m_count->n++;
}
return *this;
}
//*重载
T& operator*()
{
return *m_ptr;
}
//->重载 4+3=7
T* operator->()
{
return m_ptr;
}
private:
//智能指针释放控制的对象
void release()
{
m_count->n--;
if (m_count->n < 1)
{
delete m_ptr;
m_ptr = nullptr;
delete m_count;
m_count = nullptr;
}
}
T* m_ptr;
counter* m_count;
};