关于c++:6C基础智能指针

2次阅读

共计 2654 个字符,预计需要花费 7 分钟才能阅读完成。

程序应用动态内存起因:

  • 不晓得本人须要多少对象;
  • 不晓得对象精确类型;
  • 须要多个对象间共享数据

shared_ptr

shared_ptr/weak_ptr 的“计数”在支流平台上是原子操作,没有用锁,性能不俗

auto r = make_shared<int>(42);
r=q  // 给 r 赋值,令他指向另一个地址,递增 q 指向的对象的援用计数,递加 r 原来指向对象的援用计数,r 原来指向的对象主动开释 

当一个 shared_ptr 绑定到一个一般指针时,就将内存治理责任交给了 shared_ptr,就不能再用内置指针来拜访 shared_ptr 指向的内存。shared_ptr 能够协调对象的析构,但仅限于其本身的拷贝之间。所以举荐用 make_shared 而不是 new,就能在调配对象的同时与 shared_ptr 与之绑定,从而防止无心中将同一块内存绑定到了多个独立创立的 shared_ptr 上

以下调用,将一个长期 shared_ptr 传递给 process。当这个调用表达式完结时,这个长期对象会被销毁,它所指向的内存会被开释

1.
int *x(new int(1024);
process(x);   // 不非法,不能 int* 转换为 shared_ptr<int>     void process(shared_pt<int> ptr){}
process(shared_ptr<int>(x));  // 非法,但内存会在 Process 中被开释
int j=*x  // 未定义,x 是个闲暇指针

2.
shared_ptr<int> p(new int(42));
int *q = p.get();
{
// 新程序块
shared_ptr<int>(q);
}  // 程序块完结,q 被成果,它指向的内存被开释
int foo = *p;  // 未定义 
reset(p 指向的对象援用计数 -1)常常与 unique 一起,管制多个 shared_ptr 共享的写时复制:if(!p.unique())
p.reset(new string(*p));
*p += newVal;

unique_ptr(领有他指向的对象惟一管理权,ptr 销毁对象也销毁)

不能拷贝或者赋值 unique_ptr,能够 release/reset 将指针所有权从一个 unique_ptr 转移给另一个

//release 将 p1 置空,是切断对象的管理权,如果不必的话要本人开释资源,auto to_del = p1.release(); delete to_del;
unique_ptr<string> p2(p1.release());  
unique_ptr<string> p3(new string("xx"));
p2.reset(p3.release());  //reset 开释了 p2 原来指向的内存 

不能拷贝 unique_ptr 有个例外:能够拷贝或者赋值一个将要被销毁的 Unique_ptr。比方从函数返回一个 Unique_ptr

weak_ptr。创立时要用 shared_ptr 来初始化

auto p = make_shared<int>(42);
weak_ptr<int> wp(p);   //wp 弱共享 p,援用计数未扭转,wp 指向的对象可能被开释掉,用 wp 拜访要用 lock
dered 成员调用 check,查看应用 vector 是否平安以及 curr 是否在非法范畴内;std::string& StrBlobPtr::deref() const{auto p = check(curr,"dereference past end");
return (*P)[curr];
}

通过援用计数的形式来实现多个 shared_ptr 对象间的资源共享。

include <iostream>
#include <thread>
#include <mutex>///
using namespace std;
template
class SharedPtr{
public:
SharedPtr(T* ptr = nullptr)
: _ptr(ptr)
, _pCount(new int(1))
, _pMutex(new mutex)
{
// 如果是一个空指针对象,援用计数给 0
if (ptr == nullptr)
*pCount = 0;
}
SharedPtr(SharedPtr<T>& copy)
    : _ptr(copy._ptr)
    , _pCount(copy._pCount)
    , _pMutex(copy._pMutex)
{if (_ptr)
        AddCount();}
SharedPtr<T>& operator=(const SharedPtr<T>& copy)
{
    // 避免自赋值
    if (_ptr != copy_ptr){
        // 开释_ptr 旧资源
        Release();
        // 共享 copy 对象资源
        _ptr = copy._ptr;
        // 计数减少
        _pCount = copy._pCount;
        _pMutex = copy._pMutex;
        if (_ptr)
            AddCount();}
    return *this;
}
T& operator*() { return *_ptr;}
T& operator->() { return _ptr;}
// 查看以后计数
int UseCount() { return *_pCount;}
// 获取原始指针
T* Get(){ return _ptr;}
// 如果有新对象,减少援用计数
int AddCount()
{
    // 为保障多线程下的线程平安,执行锁操作
    _pMutex->lock();
    ++(*_pCount);
    _pMutex->unlock();
    return *_pCount;
}
// 如果有对象调用析构,缩小援用计数
int SubCount()
{_pMutex->lock();
    --(*_pCount);
    _pMutex->unlock();
    return *_pCount;
}
~SharedPtr()
{Release();
}
private:
    // 开释资源
    void Release()
    {
        // 如果援用计数减为 0,则开释资源
        if (_ptr && SubCount() == 0){
            delete _ptr;
            delete _pCount;
        }
    }
private:
    int* _pCount;  // 援用计数
    T* _ptr;  // 指向治理资源的指针
    mutex* _pMutex;  // 互斥锁
};
int main()
{SharedPtr<int> sp1(new int(10));
    cout << "Before Add SP2:" << sp1.UseCount() << endl;
    SharedPtr<int> sp2(sp1);
    cout << "After Add SP2:" << sp1.UseCount() << endl;
    
    return 0;
}
正文完
 0