C++primer 阅读笔记---------------动态内存

该博客用于记录自己在阅读过程中不懂的知识点,很少用到但比较重要的知识点以及模棱两可的知识点


函数外的对象以及static对象, 类的static数据成员存储在静态内存,使用之前分配,程序结束销毁,栈内存用于保存函数内的非static变量,仅在该内存块存在,而动态分配的对象则存储在堆中


为了内存的安全,新的标准库提供类两种智能指针,shared_ptr允许多个指针指向同一个对象,unique_ptr独占式,还有一个week_ptr伴随类,它是一种弱引用,指向shared_ptr所管理的对象

shared_ptr<T> sp
unique_ptr<T> up

p.get() //返回p中保存的内置指针,如果智能指针释放类它的对象,则 返回指针所指对象也就没了
swap(p1, p2)
p1.swap(p2)

shared_ptr独有的操作
make_shared<T> (args) //返回一个shared_ptr,指向一个动态内存分配 的类型为T的对象,args初始化,最安全,替代 new
shared_ptr<T>p(q) //p是q的拷贝,q中的指针必须要能转换为 T*,并且q中的计数器会增加
p = q //会递减p原来指向对象的引用计数,递增q
p.unique() //若p.use_count()为1,则为true,否则false
p.use_count() //返回与p共享对象的只能指针数,效率可能很 慢,多用于调试

使用动态内存的原因大概有三个:
不知道自己需要使用多少对象 //容器类的元素都在堆上
不知道所需对象的准确类型
需要在多个对象间共享数据

虽然使用new和delete直接管理内存不安全,但我们还是应该了解
当使用new时,使用定位new向new传递额外参数
int *p = new (nothrow) int; //分配失败返回空指针,不再抛异常
指针delete过后,就变成类空悬指针,指向一块曾经保留数据对象但现在已经无效的内存的指针
接受指针参数的智能指针构造函数是explicit的,所以我们不能将一个内置指针隐式转换为一个智能指针
shared_ptr<int> p1 = new int(1024) //错误, 拷贝,不能隐式转换
shared_ptr<int> p1 (new int(1024)) //正确,直接初始化形式
统样的道理,返回时:
shared_ptr<int> clone(int p) {
return new int(p); //错误
return shared_ptr<int> (new int(p)); //正确
}

shared_ptr<T> p(q) //使用只能指针p管理内置指针q使用new分配的内存块
shared_ptr<T> p(u) //p从u(unique_ptr)那接管对象所有权,u置为空
shared_ptr<T> p(q, d) //使用可调用对象d替代delete
shared_ptr<T> p(p2, d) //p是p2的拷贝,但使用可调用对象d替代delete
p.reset() //将p置为空
p.reset(q) //p指向q
p.reset(q, d)

尽量避免混合使用内置指针和只能指针,也不要用get初始化另一个智能指针或者为另一个智能指针赋值

unique_ptr没有shared_ptr的make_shared(),定义unique_ptr时,需要绑定一个new返回的指针上,和shared_ptr一样必须采用直接初始化形式

unique_ptr<T> u1
unique_ptr<T, d> u2
unique_ptr<T, d> u(D) //类型为d的对象D代替delete
u = nullptr
u.release() //u放弃对指针的控制权,返回内置指针,将u置为空
u.reset() //释放对象
u.reset(q) //如果内置指针q存在,则u指向此对象,否则置为空
u.reset(nullptr)

unique_ptr不能拷贝或赋值,但有个例外,可以拷贝或赋值一个将要被销毁的
unique_ptr<int> clone(int p){
return unique_ptr<int> (new int(p));
}
或者返回一个局部对象的拷贝
unique_ptr<int> clone(int p){
return unique_ptr<int> ret(new int(p));
}
这种拷贝比较特殊,后面讨论它的特殊原因(挖坑)

weak_ptr是一种弱共享的指针,它必须指向一个由shared_ptr管理的对象,但weak_ptr不会影响计数器,因此不能直接使用weak_ptr,借助lock(),同时创建一个weak_ptr时要用一个shared_ptr来初始化
auto p = make_shared<int>(10);
weak_ptr<int> wp(p);
if(shared_ptr<int> np = wp.lock()){ //当wp指向的对象已经被销毁时返 回空的shared_ptr,if不成立

}

weak_ptr<T> w
weak_ptr<T> w(sp)
w = p
w.reset()
w.use_count() //与w共享对象的shared_ptr的数量
w.expired() //w.use_count()为0返回true
w.lock()

使用new动态分配的数组实际上得到的是一个数组元素类型的指针,所以不能对动态数组调用begin和end

可以使用智能指针管理动态数组,当管理的是动态数组时可以下标访问
unique_ptr<int []> up(new int[10]);
up[0] = i;

使用new缺乏一定的灵活性,因为它将内存分配和对象构造结合在了一起,delete类似,allocator类将内存分配和对象构造分开来
allocator<T> a //定义了一个allcator对象,它可以为类型为T的对象 分配内存
a.allocate(n) //分配保存n块T类型的对象的内存
a.deallocate(p, n) //释放从p开始的内存,该内存保存了n个T类型对象, 此时p和n必须和分配时一样,释放前要对其中的对 象执行destroy()
a.constructor(p, args) //p是一个类型为T*的指针,在p所指内存构建一 个对象,args被传递给所构建对象的构造函数
a.destroy(p) //p为T*指针,对所指对象执行析构函数

uninitialized_copy(b, e, p2); //b,e迭代器范围内的元素拷贝到p2迭代 器指定的原始内存
uninitialized_copy_n(b, n, p2); //迭代器b开始,拷贝n个
uninitialized_fill(b, e, t); //b,e范围创建对象,值为t
uninitialized_fill_n(b, n, t);

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值