使用智能指针需包含以下头文件:#include <memory>
shared_ptr类
shared_ptr允许多个指针指向同一个对象
支持的操作:
1 | shared_ptr<T> sp; //空智能指针,可以指向类型为T的对象 |
shared_ptr和new结合使用
1 | shared_ptr<double> p1(new int(1024)); //p1指向一个值为42的int |
改变shared_ptr的方法
1 | shared_ptr<T>p(u) //p从unique_ptr u那里接管了对象的所有权:将u置为空 |
自定义释放操作
1 | // 定义自己的释放函数 |
unique_ptr类
与shared_ptr不一样,某个时刻只能有一个unique_ptr指向一个给定对象。
1 | unique_ptr<int> p(new int(42)); //unique_ptr必须采用直接初始化形式,而不能采用拷贝和赋值 |
unique_ptr的常见操作
1 | unique_ptr<T> u1; //空unique_ptr |
赋值和拷贝
我们可以拷贝或赋值一个将要销毁的unique_ptr
例如: return unique_ptr<int><new int(p)>
赋值和拷贝
自定义销毁操作
1 | void end_connection(connection *p) {disconnect(*p);} //定义自己的释放 |
weak_ptr类
weak_ptr是一种不控制所指向对象生存周期的智能指针,它指向一个由shared_ptr管理的对象。当最后一个指向shared_ptr被销毁时,对象就会被释放。
weak_ptr支持的常见操作
1 | weak_ptr<T> w; //空weak_ptr |
直接管理内存
分配
用new运算符分配内存,使用delete释放new分配的内存
int *p = new int; //p指向一个动态分配的,未初始化的无名对象
string *ps = new string //ps指向一个动态分配的空string
直接初始化
1 | int *pi = new int(1024); |
使用列表初始化
1 | vector<int> *pv = new vector<int>{0,1,2,3,4,5,6,7,8}; |
进行值初始化:在类型名后加一对空括号即可
1 | string *ps = new string(); //初始为空string |
动态分配的const对象
//初始化为一个const int
1 | const int *p = new const int(1024); |
释放内存
如果分配了内存没有释放,会造成内存空间耗尽,也称为内存泄漏。当内存耗尽时,就无法再重新分配内存。默认情况下当new无法再分配动态内存时,会抛出一个bad_alloc异常。我们可以添加nothrow来阻止它抛出异常,例如:
1 | int *p1 = new int; //如果分配失败,new抛出std::bad_alloc |
释放格式:
delete p;
技巧:delete之后重置指针
int *p(new int(43)); //p指向动态内存
auto q = p; //q和p指向相同的内存
delete p; //p和q均变为无效
p = nullptr; //指出p不再绑定到任何对象
动态数组
分配形式:
int *p = new int[get_size()]; //p指向第一个int
类型别名:
1 | typedef int Array[42]; //Array表示42个int的数组类型 |
初始化
1 | int *p = new int[10](); //10个值初始化为0 |
释放
1 | delete []p; |
智能指针和动态数组
用unique_ptr管理动态数组
1 | unique_ptr<int[]> up(new int[10]); |
支持的操作
1 | unique_ptr<T[]> u(p); //u指向p指向的动态数组 |
shared_ptr管理动态数组
为了使用shared_ptr,必须提供一个删除器
1 | shared_ptr<int> sp(new int[10], [](int *p){delet[] p}) |
局限:未定义下标运算符,且不支持指针的算术运算
1 | for(size_t i = 0; i!=10; i++){ |
allocator类
使用allocator可以先分配空间,后构造对象。
1 | allocate<string> alloc; //可以分配string的allocator对象 |
常见操作
1 | allocator<T>a; //可以分配T类型的allocator对象 |
1 | auto q = p; |
警告:
不能在未构造对象的情况下使用原始内存
销毁动态数组
1 | while(q != p){ |
拷贝和填充未初始化内存的算法:
1 | //这些函数在给定目的位置创建元素,而不是由系统分配内存给它们 |
1 | //假设有一个int的vector vi,希望将其内容拷贝到动态内存中 |