C++:动态内存 与 智能指针

  • 静态内存:保持局部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)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

绫零依

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值