程序使用动态内存原因:
- 不知道自己需要多少对象;
- 不知道对象准确类型;
- 需要多个对象间共享数据
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;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。