智能指针
new 请求内存 delete 释放内存
int * p = new int;
delete p;
========================
int * p = new int[100];
delete [] p;
shared_ptr
#include <memory>
std::shared_ptr<int> p;
p = make_shared<int>(100);
//或者
std::shared_ptr<int> p {new int(100)};
//或者
std::shared_ptr<int> p (new int(100));
//或者自己定义删除函数
std::stared_ptr<FILE> p{fp, close_file}
//close_file是自己定义的一个关闭文件的函数,用括号应该也是可以的 c++新特性
int *tp = p.get();
//得到裸指针
p.reset();
//不指向原来的内存
p.reset(new int(100));
//有参调用
普通指针有的操作,shared_ptr都可以进行
struct Bar { int i = 123; };
struct Foo { Bar bar};
int main()
{
shared_ptr<Foo> f = make_shared<Foo>();
cout << f.use_count() << endl;//prints 1
shared_ptr<Bar> b(f, &(f->bar));
cout << f.use_count() << endl; // prints 2
cout << b->i << endl; // prints 123
}
上述代码,增加对成员的指针,智能指针的count也会加一
unique_ptr
指针被销毁的同时,其绑定的区域也会被释放,不需要手动释放内存
int * p = new int[100];
/*
一些代码
*/
delete []p;
上面的代码看似很正确,但如果在中间“一些代码”那理抛出异常,p将不会被delete,内存就不会被释放
unique_ptr<int> up = make_unique<int>(100);
//c++11中make_unique并没有加进来
int *tup = up.get();
up.reset();
up.reset(new int(50));
int *tup = up.release();
//解绑操作,解绑后up被变成nullptr,返回值为up原本指向资源的裸指针
不能普通拷贝,应为不能复制控制权,但可以转移
unique_ptr<int> up = make_unique<int>(100);
unique_ptr<int> up2(up.release());
//转移1
unique_ptr<int> up2 = move(up);
//转移2
默认情况下使用 new和delete,可以自己写申请和释放函数,绑定释放函数是在编译期,避免了运行时绑定的时间损耗,shared_ptr是运行时绑定,方便
unique_ptr<int, decltype(&my_delete)> up{my_new(100), my_delete};
//用()代替{}也是可以的
//使用需要在模板参数里声明释放函数的类型
//decltype(&my_delete)是一个函数指针,指向自定义的释放函数
unique_ptr作为函数传参时,无法编译通过,用两种方式解*up
和 up.get()
一是把资源作为参数传进去 二是将裸指针作为参数
注意!如何想用函数改变unique_ptr本身,可以形参为unique_ptr的引用
注意!!!unique_ptr可以作为函数的返回值,你可能疑惑,不应该return move(up)
吗,return move(up)
没问题,但return up也没问题,因为编译器会识别这里需要的不是copy构造而是move构造
weak_ptr
对资源非拥有式,没有管理权限,不能控制资源的释放,访问资源要创建临时的shared_ptr,但可以检查资源是否存在
因为shared_ptr有环形依赖,就是互相引用互锁了,笔者觉得很好懂,就不记录了
初始化weak_ptr需要shared_ptr或weak_ptr
wp.lock()
会返回一个shared_ptr,如果被释放了会返回nullptr