以下内容总结自c++ primer
智能指针
类似常规指针,但可以自动释放所指向的对象
- shared_ptr:允许多个指针指向同一个对象,
reset
手动释放 - unique_ptr:独占所指向的对象,可通过
release
释放对对象的控制权,但同时需要将指向的对象赋值给其它智能指针 - weak_ptr:伴随类,是一个弱引用,指向shared_ptr所管理的对象,在确定是否应释放对象时,
shared_ptr
并不把其统计在内。
这三种类型都定义在memory头文件中。
//可以指向string的一个空指针
shared_ptr<string> p1;
make_shared:安全分配和使用动态内存的方法
shared_ptr<T> p1 = make_shared<T>(args);
拷贝智能指针初始化:
q是shared_ptr,此操作回递增q中的计数器。其中的指针必须能转换为T*
shared_ptr<T> p(q);
p和q都是shared_ptr,所保存的指针必须能互相转换。此操作会递减p的引用计数,递增q的引用计数;若p的引用计数变为0,则将器管理的原内存时释放。
p=q;
智能指针和动态数组
标准库提供了一个可以管理new分配的数组的unique_ptr版本:
//up指向一个包含10个未初始化int的数组
unique_ptr<int[]> up(new int [10]);
up.release();//自动用delete[]销毁其指针
unique_ptr
指向一个数组时,不能使用点和箭头成员运算符,但可以使用下标运算符来访问数组元素,如up[0]
。
如果要用shared_ptr
管理动态数组,必须自己提供自己定义的删除器:
shared_ptr<int> sp(new int[10],[](int*p){delete[]p;});
sp.reset();//使用提供的lambda释放数组
allocator类
定义在头文件memory中,它帮助我们将内存非配和对象构造分离开来。其分配的内存相比于new,是原始的未构造的。
类似vector,allocator是一个模板。为了定义一个allocator对象,我们必须指明这个allocator可以分配的对象类型。当一个allocator对象分配内存时,它会根据给定的对象类型来确定恰当的内存大小和对齐位置。
allocator<string>alloc;//可以分配string的allocate对象
auto const p = alloc.allocate(n);//分配n个未初始化的string
操作 | 描述 |
---|---|
allocator<T> a | 定义了一个名为a的allocator对象,它可以为类型为T的对象分配内存 |
a.allocate(n) | 分配一段原始的、未构造的内存,保存n个类型为T的对象 |
a.deallocate(p,n) | 释放从T*指针p中指针开始的内存,这块内存保存了n个类型为T的对象;p必须是一个先前由allocate返回的指针,且n必须是p创建时所要求的大小。在调用deallocate之前,用户必须对每个在这块内存中创建的对象调用destroy。 |
a.construct(p,args) | p必须是一个类型为T*的指针,指向一块原始内存;arg被传递给类型为T的构造函数,用来在p指向的内存中构造一个对象。 |
a.destroy(p) | p为T*类型的指针,此算法对p指向的对象执行析构函数。 |
auto q=p;
alloc.construct(q++);//q原始位置对应空字符串。
alloc.construct(q++,10,'c');//q原始位置对应cccccccccc。
alloc.construct(q++,"hi");//q原始位置对应hi
必须使用construct构造对象后,才能使用allocate返回的内存,否则,其行为是未定义的。
用完对象后,必须对每个元素进行destroy:
while(q!=p)
alloc.destroy(--q);//释放真正构造的string
一旦元素被销毁后,可以重新使用这部分内存保存其它string,也可以返还给系统。释放内存通过调用deallocate来完成:
alloc.deallocate(p,n);