why:正确释放动态申请的内存
how:smart pointer(#include<memory>)
- shared_ptr
- unique_ptr
- weak_ptr
shared_ptr:允许多个指针同时指向同一个对象
(1)补充:
1、make_shared<T>(args),中的args要符合前面的类型T的参传入数格式
2、 shared_ptr<T>(args),其中args只能以()的形式来初始化shared_ptr,因为shared_ptr的构造函数是explict的,不允许T* ptr这种类型隐式转换成share_ptr,错误样例: shared_ptr<int> clone(int p) { return new int(p); }
3、p.get()返回指向智能指针管理对象的内置指针
4、建议使用shared_ptr(new int() )来初始化shared_ptr,如果int* p = new int(); shared_p(p),如果只有一个shared_ptr指向该内存,p所指空间已被释放,可能会出现 double free 和解引用非法内存,但是最好使用make_shared代替shared_ptr(new int() )
(2)管理
shared_ptr在调用一次拷贝构造函数时(传对象参数,return对象,显示调用拷贝构造函数),计数器+1,shared_ptr在一次赋值,=号左边的引用计数器-1,=号右边的引用计数器+1,一次声明周期结束时,计数器会-1当shared_ptr引用计数值=0,会自动释放自己所管理的对象shared_ptr保证,只要有任何指针引用对象,对象就不会被释放掉
(3)运用动态分配内存的理由不知道要使用多少对象: 例如容器不知道所需对象的准确类型: 例如为实现多态而动态申请父类元素指针多个对象共享数据动态分配内存程序员容易造成内存泄露,所以要用智能指针
(4)直接管理内存:
int* p = new int; //*p是一个未定义的值
int* p = new int(); //*p被初始化为0
int* p = new int(10); //*p初始化为10对象会调用默认构造函数来初始化对象,但是内置变量必须在默认构造函数中初始化,否则值也是未定义的内置指针管理的动态内存在显式释放前都一直存在,需要手动释放
(5)常犯的错误:
忘记delete new申请的动态内存(new[]/delete[]) // 没删
解引用已经被释放的对象 // 删了又用
同一块内存别释放两次 // 多删
编程的好习惯是:delete之后重置指针=nullptr可以保证指针不会使用已经delete掉的空间
注意事项
不要混用普通指针和智能指针,比如:int *p = new int(10); void b(shared_ptr<int>(p)){ return; }; *p = 1000; //p指向对 象已经被释放掉
unique_ptr:一个对象只能被一个指针指向
初始化方式:
1、unique_ptr<int>(new int (10))的形式直接初始化,c++14后可以用make_unique
2、unique_ptr<int>p(q) //error,不存在允许拷贝赋值,所以也没有类似shared_ptr类似的函数// 观察编译器如何诊断unique_ptr出现赋值,拷贝这种错误
#include<iostream>
#include<memory>using namespace std;
int main(int argc, char* argv[])
{
unique_ptr<int>uPtr(new int(20));
unique_ptr<int>p1(uPtr); // use of deleted function
unique_ptr<int>p2 = uPtr; // use of deleted function
}
u.reset(q),如果reset不为空,则会先把u指向的内容释放掉,再让u管理内存q
不能拷贝赋值的unique_ptr有一个特列:
思考:为什么shared_ptr没有release函数
因为shared_ptr是可共享的,而且每个shared_ptr的副本都可以delete指向的对象,而 unique_ptr不能共享内存,所以要由对应的unique_ptr释放内存
weak_ptr:指向share_ptr管理的对象
顶一个