一 、C++的内存泄漏是什么 如何避免,new 和delete的用法
内存泄漏:申请一块内存后,没有释放掉。表现为程序运行时间越长内存占用越大,最终占用全部 内存,系统崩溃。---由程序员申请的内存 没有指针指向它 那这块内存就泄露了
new delete
delete :释放p指向的内存 不删除p 指针p依旧可以指向别的地方
栈
堆
堆
删除p指针后可将p为nullptr空指针(C++11新特性)
二、共享指针 shared_ptr 如何帮你自动管理内存
共享指针 :记录有多少个共享指针指向这个内存 当为0时会自动释放--引用计数
如果裸指针和共享指针同时指向一个地方那么当计数为0时 共享指针依旧会释放该内存,裸指针再访问会有问题 所以应该避免混用
make_shared是一个模版 可接受 一个类型和参数 (推荐)
new
举例通过析构函数观察销毁情况
p.use_count()查看计数个数,p.reset() 释放空间 也可指向新的地址 全部释放后 调用析构函数
p.reset(q) //q为智能指针要指向的新对象
三、shared_ptr 补充知识点
1.可自定义销毁方式---关闭文件 断开网络等
2.别名 用来访问类的成员变量
b具有 f指向内容Foo bar 的管理权 ,如果b不被销毁则该内存不能被销毁
也就是说 当想要访问一个类的实例的成员属性时 使用此功能防止 这个实力被销毁无法访问属性
3.危险操作--使用共享指针避免使用 delete
4.额外内存开销--性能极为苛刻不合适
四、为什么你应该尽可能使用unique_ptr替换裸指针*
1.unique_ptr:
独占资源,同一时间只有一个智能指针可以指向该对象
unique_ptr 不像 shared_ptr 一样拥有标准库函数 make_shared 来创建一个 shared_ptr 实例。要想创建一个 unique_ptr,我们需要将一个new 操作符返回的指针传递给 unique_ptr 的构造函数。
std::make_unique 是 C++14 才有的特性。
// 示例:
int main()
{
// 创建一个unique_ptr实例
unique_ptr<int> pInt(new int(5));
cout << *pInt;
}
unique指向对象被销毁时 其绑定资源会自动释放 不需要手动delete
2.unique 相对裸指针的好处
当p->foo() 出现异常时 delete不会被执行 会造成内存泄漏
使用unique——ptr 资源一定会被释放
3.获得裸指针
依旧可通过 ->get获得裸指针
4.释放资源
直接释放资源 将up指向nullptr
释放资源指向新的内存 将up指向Ball实例
可使用release解绑
5.不支持普通拷贝
不可复制控制权但是可以转移
release转移
move转移
6.new delete
默认情况下使用new delete 来分配和释放内存
均可自定义替换 比shared_ptr更复杂 因为 unique_ptr绑定发生在编译期 shared 在运行时绑定
五、如何在函数间传递unique_ptr?
由于不能复制 但是函数在传值的时候需要复制 因此需要特别注意
编译会出错
1.传递
避免一,传递*up up 是指针 而*up为指针指向内容
传递 *up
,实际上传递的是指向对象的原始指针,而不是 unique_ptr
对象本身。这意味着在函数内部,你只能访问对象,但不能管理其所有权。unique_ptr
仍然在调用函数结束后拥有对象的所有权
避免二,使用up.get()获取裸指针进行传递
2.unique_ptr传递
move 转移指针的控制权
move(up) 是用来将对象从一个地方移动到另一个地方的函数 这里将up移动到了pass_up函数中,意味着 up的所有权被转移到了函数的参数‘unique_ptr<int> up’中
unique_ptr作为返回值
六、weak_ptr 是什么,为什么要用它?
1.weak_ptr特性
是shared_ptr的伴侣 是一个观察者 对资源的引用时非拥有似的 没有资源的管理权限
不能进行资源的释放 访问时需要创建一个临时的 shared指针 可以检查资源是否存在
2.为什么需要需要weak_ptr
shared_ptr会发生环形依赖--循环引用 计数无法记为0 无法释放
1.weak_ptr使用时需要配合shared_ptr使用如main函数前三行
2.weak_ptr想要访问资源需要使用 .lock()函数使用
若访问内容未被释放,会返回一个shared_ptr
若访问内容已被释放,会返回一个nullptr
因此可以判断资源是否存在;