- 静态内存:保持局部static对象、类static数据成员、定义在函数之外的变量
- 栈内存:函数内非static对象
- 自由空间(free store)或堆(heap): 储存动态分配(dynamically allocate)的对象
智能指针 smart pointer
头文件memory中
- shared_ptr 可多个指针指向同一个对象
- unique_ptr 一个指针独占所指向的对象
- weak_ptr 弱引用,指向shared_ptr所管理的对象
shared_ptr 与 unique_ptr
shared_ptr<T> sp; //创建空指针
unique_ptr<T> up;
if(p); //作为条件使用判断是否为空
*p
p->mem
p.get() //返回p中保持的指针
swap(p,q) //交换指针
p.swap(q)
shared_ptr
无论何时拷贝一个shared_ptr,与其关联的 引用计数器(reference count) 都会增加。销毁一个shared_ptr或赋予其一个新的值,计数器减一。一旦一个shared_ptr的计数器变为0,就会自动释放其所管理的空间。
- make_shared(args)
- 动态分配一个T对象,用args进行初始化,返回一个shared_ptr.
- 安全的动态分配和使用动态内存的方法
- shared_ptr p(q)
- shared_ptr p(q,d)
- p.reset()
- p.reset(q)
- p.reset(q,d)
- (q可以时shared_ptr 、T*)
- (d为可调用对象,删除器(deleter),用于替代delete)
- void deleter(T* p);
- p = q
- p的引用计数将减小
- q的引用计数将增加
- p.use_count()
- 指向p所指向的对象的shared_ptr的数量
- p.unique()
- true: p.use_count()为1
- false: 不为1
unique_ptr
某个时刻只能有一个unique_ptr指向一个给定对象。unique_ptr被销毁时,其所指向的对象也被销毁。
- 只能通过绑定到一个指针来初始化
- 不支持拷贝、赋值
- 但是可以移动,所以可以return一个unique_ptr
- unique_ptr u
- unique_ptr<T,D> u(d) D为删除器类型,d为删除器对象
- u = nullptr 释放并置空
- u.release() 放弃对指针的控制权,返回指针,并将置空
- u.reset() 如果原来不为空,则释放原指向的对象
- u.reset(q)
weak_ptr
不控制所指向对象的生存期,指向一个shared_ptr管理的对象。将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。
- weak_ptr w
- weak_ptr w(sp) 绑定一个shared_ptr,与sp指向相同对象
- w = p p可以是shared_ptr或weak_ptr
- w.reset()
- w.use_count() 与w共享对象的shared_ptr的数量
- w.expired() true:w.use_count() == 0
- w.lock() 如果expired()为true,返回空的shared_ptr;否则返回指向w的对象的shared_ptr。
new
//对内置类型
new int(); //值初始化,值为0
new int; //默认初始化,未定义的值
new int[42]; //"动态数组"
//推断
auto p1 = new auto(obj);
//const对象,没有默认构造函数的类型必须显式初始化
const int* p = new const int(42);
- 若分配失败(空间耗尽),new返回空指针。并抛出bad_alloc异常。而new …[]抛出bad_array_new_length异常。
- 使用nothrow对象禁止抛出异常
new (nothrow) int;
- (nothrow与bad_alloc定义在头文件new中)
- 释放动态数组要加[]: delete [] pa;
- 使用unique_ptr管理动态数组
unique_ptr<int[]> up(new int[42]);
当unique_ptr指向数组时,不能使用.和->运算符,但可以使用[]
- shared_ptr不支持管理动态数组,需要提供自定义的删除器。
shared_ptr<int> sp(new int[42], [](int *p){delete[] p;});
allocator类
实现内存分配与对象构造分离。可以先分配内存,在需要时构建对象。
- allocator a
- a.allocate(n) 分配一段原始的、未构造的内存,可以保存n个T对象.
- a.deallocate(p,n) 释放p指向的allocate分配的空间。n必须与allocate时的大小相同。调用之前,必须对每个在这块内存中创建的对象调用destroy
- a.construct(p, args) 在原始空间构造对象
- a.destroy§ 析构
伴随算法:
- uninitialized_copy(b,e,p) 将迭代器指示的范围b和e之间的元素,拷贝到p指向的未构造的内存中
- uninitialized_copy_n(b,n,p) 从迭代器b指向的位置开始拷贝n个元素到p指向的未构造的内存中
- uninitialized_fill(b,e,t) 在迭代器b和e指定的原始内存中创建多个t的拷贝
- uninitialized_fill(b,n,t)