第十二章 动态内存

来源:互联网 发布:iptv服务器软件 编辑:程序博客网 时间:2024/05/17 09:30

程序除静态内存和栈内存,还有自由空间(free store)or 堆(heap)。
使用动态内存容易造成内存泄漏:忘记delete new分配的空间。
share_ptr类:模板。最好用make_shared函数来分配内存。

shared_ptr<int> p1 = make_shared<int> ();shared_ptr<string> p2 = make_shared<string> (6, '6');shared_ptr<int> p3(p1);//允许多个指针指向同一个对象,shared

refrence count:比较重要,变为0,自动销毁管理对象,释放相关内存。 拷贝递增,赋新值或销毁时递减,如局部shared_ptr离开其作用域。(注:将shared_ptr存入容器,而后不在需要全部元素,记得erase。)

类使用动态内存:1 不知道自己需要使用多少对象——容器类。 2 不知道对象准确类型。 3 多个对象间共享数据——类成员引用相同的底层数据,只有当引用计数为0时销毁底层数据。
释放一块非new分配内存或者同一内存释放多次,undefined。
然而释放一个空指针总没错:*p0 = nullptr; delete p; //OK

空悬指针(dangling pointer):delete之后,指针任然保存内存地址,即它指向一块曾经保存数据但现在已经无效的内存。最好:
int *p = new int(666); delete p; p = nullptr; //指针置空
但是多指针指向同一内存时要多加小心。

shared_ptr<int> p1 = new int(666);//error:不能将内置指针隐式转换为智能指针shared_ptr<int> p2(new int(666)); //OK;直接初始化/*特别是在函数返回类型为智能指针时要注意*/shared_ptr<int> func1(int p){ return new int(p);} //wrong!shared_ptr<int> func2(int p){ return shared_ptr<int>(new int(p));}//OK!
void process(shared_ptr<int> ptr){  //使用ptr}/*当传递给该函数一个shared_ptr类型参数时,引用计数至少为2*/shared_ptr<int> p1(new int(666)); //引用计数1process(p1);//拷贝,函数中引用计数2,p1离开作用域销毁,变为1,并未释放内存,p1仍然指向分配的内存,可继续使用,注意后续处理。/*当传递给该函数一个内置指针时*/int *p2(new int(666));process(p2);//error:不能隐式转化process(shared_ptr<int>(p2));//OK,用完之后引用计数就为0了,内存已经释放!

使用get()时需注意,get()返回指针的代码不能delete此指针,否则原来的shared_ptr将变成空悬指针。不要用get()初始化或为另一个智能指针赋值。

reset():

if (!p.unique()) //检查我们是否是当前对象的唯一用户     p.reset(new int(*p));//不是,分配新的拷贝//现在是唯一用户,操作p

智能指针确保发生异常时的资源释放:

void func1(){  shared_ptr<int> p1(new int(666));  //抛出异常} //函数结束时,自动释放资源void func2(){  int *p2 = new int(666);  //delete之前异常,不会释放资源  delete p2;}  

使用智能指针管理的不是new分配的内存,要传递给它一个删除器:

shared_ptr<T> p(i, c);//c是执行析构操作的可调用对象,是我们自定义的删除器

unique_ptr不支持普通的拷贝或赋值操作,可以拷贝或赋值一个将要被销毁的unique_ptr,例如从函数返回一个unique_ptr。注意release()方法并未调用delete。

unique_ptr<int> p1 = new int(666);p1.release();//并未释放内存,不要这样用auto p = p1.release();delete p;//释放了内存

weak_ptr绑定到shared_ptr来观察对象,不改变引用计数,不能用来直接访问对象,因为有可能对象不存在,需调用lock()方法:

shared_ptr<int> p = new int(666);weak_ptr<int> wp(p);if (shared_ptr<int> p1 = wp.lock()){   //lock返回ture,才能进入if语句体通过p1对对象进行操作}

尽量使用标准库容器而不是动态分配的数组!
分配一个数组,得到的是一个数组元素类型的指针,并非一个数组类型的对象!

int *p = new int [num]();//最好初始化一下delete [] p;char arr[0] //error:不能定义长度为0的数组char *cp = new char[0]; //OK,动态分配一个空数组是合法的,                        //但不能解引用cp
unique_ptr<int[]> p(new int[10]);//unique_ptr直接管理动态数组p.release();//书上说这里会自动调用delete[],因为管理的是一个数组shared_ptr<int> p1(new int[10], [](int *p) {delete [] *p;}); //shared_ptr管理动态数组需传递一个删除器,没有定义[],智能指针不支持指针算术运算,get()内置指针来访问数组元素。

allocator类:分配原始的、未构造的内存,将分配内存与对象构造分离开来,提高灵活性。

allocator<string> alloc; //可以为string对象分配内存auto p = alloc.allocate(num); //分配num个string对象//construct()方法构造;//destroy()方法销毁;//deallocate()释放内存;先destroy再释放//相关算法,copy,fill;
阅读全文
0 0
原创粉丝点击