c++ 智能指针
所需要的头文件
#include <memory>
- shared_ptr : 允许多个指针指向同一个对象;
- unique_ptr : 独占 所指向的对象
- weak_ptr : 弱引用
shared_ptr独有的操作
- make_shared函数 : 最安全的分配和使用动态内存的方法
shared_ptr<int> p3 = make_shared<int>(42);
cout<<*(p3.get())<<endl; //42
shared_ptr<string> p4 = make_shared<string>(10,'9');
cout<<*(p4.get())<<endl; // 10个9
auto p5 = make_shared<int>(); // p5 指向一个初始化的int,初始值为0
auto p6 = make_shared<vector<string>>(); //p6 指向一个动态分配的空vector<string>
// 拷贝和赋值
auto p = make_shared<int>(42);
auto q(p);
cout<<*(q.get())<<endl; // 42
auto r = make_shared<int>(43);
r = q; // r所指向的对象的引用计数器递减,没有了引用者,会自动释放
cout<<*(r.get())<<endl; // 42
shared_ptr和new结合使用
shared_ptr<double> p1;
/*
*shared_ptr<T> p(q)
* p管理内置指针q所指向的对象
* q必须指向new分配的内存,且能够转换为T*类型
*/
shared_ptr<int> p2(new int(42));
// p2 = new int(42); 错误 不能将一个指针赋值给shared_ptr
/*
*p2.reset() 若p2是唯一指向其对象的shared_ptr,reset会释放此对象
* reset 成员经常与 unique 一起使用,来控制多个shared_ptr 共享的对象,
* 在改变底层对象之前,我们检查自己是否是当前对象仅有的用户,如果不是,
* 在改变之前要制作一份新的拷贝
*/
p2.reset(new int(1024)); // p2指向一个新的对象
cout<<*(p2.get())<<endl;
if(!p2.unique())
{
p2.reset(new int(*p2)); // 我们不是唯一用户;分配新的拷贝;
}
*p2 += 22; // 现在我们知道自己是唯一的用户,可以改变对象的值
cout<<*p2<<endl; // 1046
unique_ptr
- 一个 unique_ptr 拥有 它所指向的对象。 与shared_ptr不同,某个时刻只能有一个unique_ptr 指向一个给定对象。当unique_ptr被销毁时,它所指向的对象也被销毁。
- 没有类似的make_shared的标准库函数返回一个unique_ptr,当我们定义unique_ptr时,需要将其绑定到一个new返回的指针上。
unique_ptr<double> p1;
unique_ptr<int> p2(new int(1024));
cout<<*p2<<endl; // 1024
- 由于unique_ptr 拥有它指向的对象,因此unique_ptr 不支持普通的拷贝或赋值操作
unique_ptr<string> p1(new string("Stegosaurus"));
// unique_ptr<string> p2(p1); // 错误: unique_ptr 不支持拷贝
// unique_ptr<string> p3;
// p3 = p1; // 错误: unique_ptr 不支持赋值
// 将所有权从p1 转移到 p2
/*
*u.release() u放弃对指针的控制权,返回指针,并将U置空
* 调用release()会切断unique_ptr 和他原来管理的对象间的联系,
* release返回的指针通常被用来初始化另一个智能指针赋值。
*/
unique_ptr<string> p2(p1.release()); // p1置为空
unique_ptr<string> p3(new string("Text"));
// 将所有权从p3 转移给 p2
p2.reset(p3.release());
cout<<*p2<<endl; // Test
weak_ptr
- weak_ptr 是一种不控制所指向对象生存期的职能指针,它指向由一个shared_ptr管理的对象.
- 将一个weak_ptr 绑定到一个shared_ptr 不会改变shared_ptr的引用计数。
- 一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放,即使有weak_ptr 指向对象也会被释放。所以叫做 弱 只能指针
auto p = make_shared<int>(42);
weak_ptr<int> wp(p); // wp 弱共享p, p的引用计数未改变
/*
*由于对象可能不存在,我们不能使用weak_ptr 直接访问对象,而必须调用lock,
* lock函数检查weak_ptr 指向的对象是否仍存在,如果存在,lock 返回一个指向共享对象
* 的shared_ptr
*/
if(shared_ptr<int> np = wp.lock()) // 如果存在则进入该空间
{
cout<<*np<<endl;
}
智能指针和动态数组
// unique_ptr
// up 指向一个包含0个为初始化 int的数组
unique_ptr<int[]> up(new int[10]);
// 指向数组的unique_ptr 不支持成员访问运算符 (点和箭头运算符)
up.release(); // 自动用delete[] 销毁其指针
int i;
for (i=0;i<10;++i)
{
up[i] = i;
}
// shared_ptr
// shared_ptr 不支持管理动态数组,如果希望管理一个动态数组,必须提供自己定义的删除器
shared_ptr<int> sp(new int[10],[](int *p){delete[] p;});
sp.reset(); // 使用我们自定义的lambda 释放数组
for (i=0;i<10;++i)
{
*(sp.get()+i) = i;
}
浙公网安备 33010602011771号