C++新特性(四)- auto_ptr

智能指针的概念

在传统C++中,我们用new和delete去对资源进行申请和释放,而C++11引入了智能指针的概念,让程序员不再需要关心手动释放内存。
RAII: Resource Acquisition Is initialization(资源获取即初始化). RAII的核心思想是将资源或者状态与对象的生命周期绑定,通过C++的语言机制,实现资源和状态的安全管理。理解和使用RAII能使软件设计更清晰,代码更健壮。

智能指针使得自动、异常安全的对象生存期管理可行。
智能指针的本质是类模板。

C++共有四个智能指针: auto_ptr, shared_ptr, weak_ptr, unique_ptr 其中后三个是c++11支持,并且第一个已经被c++11弃用。

1.auto_ptr

auto_ptr 可以通过将普通指针作为参数传入智能指针的构造函数实现绑定。当auto_ptr对象生命周期结束时,其析构函数会将auto_ptr对象拥有的动态内存自动释放。
auto_ptr是C++98标准库中的智能指针模板类 ,在C++11已经被废除, 可以用unique_ptr取代,功能上是相同的,unique_ptr较auto_ptr 而言,提升了安全性(没有浅拷贝),增加了特性(delete析构)和对数组的支持。
其功能如下:

  • 支持拷贝构造 (危险)
  • 支持赋值拷贝 (危险)
  • 支持operator->/operator*解引用
  • 支持指针变量重置
  • 保证指针持有者唯一

auto_ptr的构造参数可以是一个指针,或者是另外一个auto_ptr对象。注意:当一个新的auto_ptr获取了内部指针的所有权之后,之前的拥有者会释放其所有权,即被释放。

构造:

std::auto_ptr<int> p(new int(3));

拷贝构造(剪切):

auto_ptr< string > p1 (new string( "hellow" ) );
auto_ptr< string > p2( p1);  //利用p1来构造p2,p1被释放(null)

因为一块动态内存只能由一个智能指针独享,所以在调用拷贝构造或赋值运算符时都会发生拥有权转移的过程。在此拷贝构造过程中,p1将失去对字符串内存的所有权(p1为空),而p2将其获得。对象销毁时,p2负责内存的自动销毁。

赋值(剪切)

//利用已经存在的智能指针来构造新的智能指针
auto_ptr< int > p1( new int( 1024 ) );
auto_ptr< int > p2( new int( 2048 ) );
p1 = p2;

在赋值之前,由p1 指向的对象被删除。赋值之后,p1 拥有int 型对象的所有权。该对象值为2048。 p2指向null。

auto_ptr的缺点:

  1. 不能有两个auto_ptr对象拥有同一个内部指针的所有权,因为有可能在某个时机,两者均会尝试析构这个内部指针。
  2. 当两个auto_ptr对象之间发生赋值操作时,内部指针被拥有的所有权会发生转移,这意味着这个赋值的右者对象会丧失该所有权,不再指向这个内部指针(其会被设置成null)。-- 可以理解为剪切
  3. auto_ptr不支持传入deleter,所以只能支持单对象(delete object)
  4. auto_ptr不支持容器。

有问题的使用场景一:函数传参
auto_ptr拷贝赋值时是所有权转移,函数传参会发生一个拷贝,p1拷贝给p,导致其内部指针的所有权被转移给了p,导致p1指向null。

void foo(std::auto_ptr<int>p)
{
	cout<<*p<<endl;
}
int main()
{
	std::auto_ptr<int>p1 = std::auto_ptr<int>(new int(1024));
	foo(p1); // p1失去了内部指针的所有权,变为null.
	cout<<*p1<<endl;//访问空指针,程序crash
}

有问题的使用场景二:把auto_ptr放到容器中
应绝对避免把auto_ptr放到容器中,(unique_ptr)auto_ptr拷贝赋值时是所有权转移,而在容器中可能会产生临时对象拷贝赋值,临时对象获得所有权之后就析构了释放了对象。并且很难避免STL内部对容器中的元素实现赋值,这样便会使容器中多个元素被置位NULL

std::vector<std::auto_ptr<int> arr;
std::auto_ptr<int>a1(new int(1024));
arr.push_back(a1);// 编译出错。binding reference of type 'std::auto_ptr<int>&' to 'const std::auto_ptr<int>' discards qualifiers。
std::cout << peoples[5]->get_name() << std::endl; 

auto_ptr的析构函数调用的是delete不是delete [],所以不能使用智能指针数组。
判断一个auto_ptr是否为空不能使用if(ptest == NULL),应该使用if(ptest.get() == NULL)

常用成员函数

  • get函数:
    返回智能指针指向对象的指针.
  • reset函数:
    reset函数提供了默认参数,功能是取消auto_ptr对原对象的控制权,并选择性提供一个新的对象控制权.
  • realease函数:
    realease实现的功能就是将原智能指针的控制权取消,不释放原始指针.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值