动态内存与智能指针

在c++中使用new、delete或new[]、delete[]来申请、释放内存,但是有时候会忘记释放,为了更容易、安全地使用动态内存,新的标准库提出了智能指针:智能指针也是模板,auto_ptr、shared_ptr、scoped_ptr、weak_ptr、unique_ptr(c++11提出的)
.默认初始化的智能指针中保存一个空指针。解引用一个智能指针返回它指向的对象。如果在一个条件判断中使用智能指针,效果就是检测它是否为空。

auto_ptr:核心思想是资源管理权的转移,即是说在创建对象时构造函数获得资源管理权,但是在释放资源时会将资源管理权转移,这样会导致不安全问题。

shared_ptr:允许多个指针指向同一个对象,其中有一个关联的计数器,称为引用计数,无论何时我们调用构造函数、拷贝构造函数、赋值运算符重载或将它作为参数传给一个函数或作为一个函数的返回值时,其关联的计数器都会增加,当给shared_ptr赋予一个新值或者shared_ptr被销毁(例如一个局部的shared_ptr离开其作用域),计数器就会递减。当计数器为1时,当且仅当一个指针指向对象时,它就会自动释放自己所管理的对象。并释放它占用的内存。shared_ptr不直接支持管理动态数组,如果希望使用shared_ptr管理一个动态数组,必须定制自己的删除器。
shared_ptr还会自动释放相关联的内存,如:

void use_factory(T arg)
{
    shared_ptr<FOO>p=factory(arg);//p离开了作用域,它指向的内存就会自动释放掉。

}//由于p是use_factory的局部变量,在use_factory结束时它将被销毁,当p被销毁时,将递减其引用计数并检查它是否等于0,若为0.则所占的内存会被释放。



shared_ptr<FOO>use_factory(T arg)
{
    shared_ptr<FOO>p=factory(arg);
    return p;//当作为返回值时,引用计数进行了递增,p离开了作用域,但是其指向的内存不会被释放。
}

如果你将shared_ptr存放在一个容器中,而后不再需要全部元素,而只使用其中的一部分,要记得erase删除不再需要的那些元素。
scoped_ptr:实现原理是包装了new操作符在堆上分配的动态对象,不允许使用拷贝构造函数和赋值运算符重载,故需要将拷贝构造函数与赋值运算符重载私有声明,它与auto_ptr的共同点是都是用一个栈上的对象去管理一个堆上的对象,使得堆上的对象随栈上对象自动删除,但是,其不可以将指针所有权转让,只能在作用域内使用。
unique_ptr:只能有一个unique_ptr指向一个给定对象,当unique_ptr被销毁时,它所指向的对象也被销毁,它不允许拷贝和赋值,但是可以通过release或reset将之真的所有权从一个(非const)unique_ptr转移给另一个unique。其可以管理new分配的动态数组,有自己的删除器。
通常release会切断unique_ptr和它管理的对象间的联系,release返回的指针通常被用来初始化另一个智能指针或给另一个智能指针赋值。

p.release();//p不会释放内存,只是放弃了所有权。
auto p1=p.release();//正确
delete p1;

weak_ptr:不单独使用,一般配合shared_ptr来使用,解决shared_ptr的循环引用问题。它指向一个由shared_ptr管理的对象,将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数,一旦最后一个指向对象的shared_ptr被销毁,对象就会被销毁,即使有weak_ptr指向对象,对象还是被释放。

定义智能指针:
shared_ptrp;//定义,接受指针参数构造函数是explicit类型的,不能将一个内置的指针隐式转换成一个智能指针,必须使用显式初始化初始化智能指针:如:shared_ptrp(new int(1024)).
make_shared函数:标准库函数,此函数在动态内存中分配一个对象并初始化它,返回指向此对象的shared_ptr。其是最安全的分配和使用动态内存的方法,通常使用auto定义一个对象来保存make_shared的结果。

使用了动态生存期的资源的类:
1.程序不知道自己需使用多少对象。
2.程序不知道所需对象的类型。
3.程序需要在多个对象间共享数据。

猜你喜欢

转载自blog.csdn.net/xiaodu655/article/details/81334153