智能指针

现在,C++有如下智能指针,除了auto_ptr外,其他都是11标准引入的。

所有的智能指针都是模板化(class template)的。so,可以使用xxxx_ptr<T>的形式来满足不同的数据类型。

① unique_ptr

smart pointer with unique object ownership semantics

只能有一个主人的指针,可以用于STL容器

② shared_ptr

smart pointer with shared object ownership semantics

可共享的指针

③ weak_ptr

weak reference to an object managed by std::shared_ptr

弱引用指针

④ auto_ptr

smart pointer with strict object ownership semantics

只能有一个主人的指针,不能用于STL容器

一、auto_ptr智能指针介绍

标准库提供了一个资源句柄模板auto_ptr,用于生成具体的智能指针,它们指导在用完之后如何清理资源。

1、 重载了->,*操作符

auto_ptr<Shape> aShape(new Ciccle);

aShape->draw();

(*aShape).draw();


2、类型转换酷似内建指针

auto_ptr<Circle> aCircle(new Circle);

aShape =aCircle;


3、当我们将aCircle赋值给aShape时,参与赋值的源值和目标值都受到了影响。如果aShape是非空的,那么不管它指向的是什么东西,都将会被delete掉,并且代之以aCircle所指向的东西;除此之外,aCircle也被设置成空,对于auto_ptr而言,赋值和初始化并不是真正的复制操作,它们实际上是将底层的对象的控制权从一个auto_ptr转移到另一个auto_ptr 。


4、以下两种情况不要用auto_ptr

不能指向数组,这是因为其内部实现,在析构函数里执行了delete ptr,而不是delete[] ptr。

不可能存在多个auto_ptr指向同一个对象。这是最重要的。也就是说,auto_ptr不能用作STL容器的元素。

主要由于上边这个原因,auto_ptr在C++11中已经被废弃了(虽然仍然可以使用它),推荐用unique_ptr取代之。

下边举例说明:


创建一个auto_ptr

复制代码
// 访问空的auto_ptr会出错
auto_ptr<int> p;
cout << *p << endl;

// 想模仿int* p = 5也是不行的,编译不过
// auto_ptr的operator=被重载,不是简单的赋值了。
// 不能使用=来初始化,除非对象是auto_ptr
auto_ptr<int> p = 5;

// 直接使用auto_ptr的构造函数赋初值也是不成的,因为初值必须是指针地址。
// 编译报错
auto_ptr<int> p(5);

// 可以使用地址,通过构造函数来初始化
// 不过这么搞,也就失去了其用途了:为的就是防止出现指针,结果还额外多出来个指针。
int i = 5;
int* p = &i;
auto_ptr<int> auto_p(p);
cout << *auto_p << endl;

// 只要是类型正确的指针就可以,并不验证数据有效性,只要够风骚~
int i = -10;
unsigned* p = (unsigned*)&i;
auto_ptr<unsigned> auto_p(p);
cout << *auto_p << endl;  // 输出一个好大的数,因为unsigned不考虑符号位嘛
复制代码

正确的方法是这样,在构造函数的参数里使用new。这是唯一推荐的方法。这样,等auto_ptr销毁了,保存的数据的内存也会释放。

// 唯一的推荐方法
auto_ptr<unsigned> auto_p(new unsigned(10));

也可以创建一个NULL的auto_ptr对象,然后用operator=“赋值”,右值必须也是auto_ptr对象。

这里的等号不是真正的赋值,同时会让原始的auto_ptr无效化。

auto_ptr<unsigned> auto_p1(new unsigned(10));
// 先创建了一个空的auto_ptr,然后从其他auto_ptr处获得所有权
auto_ptr<unsigned> auto_p2;
auto_p2 = auto_p1;

也可以直接在构造函数里传递所有权,效果类似。

auto_ptr<unsigned> auto_p1(new unsigned(10));
auto_ptr<unsigned> auto_p2(auto_p1);

 

对象只有一个auto_ptr的主人

参考上边的三条语句,会发现对象所有权的转移。

第一条语句执行后:auto_p1完成初始化,auto_p2还未创建。此时10的所有者是auto_p1

第二条语句执行后:auto_p2完成“初始化”,此时auto_p2是一个空对象。

第三条语句执行后:auto_p2被赋值,但是auto_p1却变成了空值。

这样的原因是auto_ptr重载了operator=,其实现类似于:

复制代码
template<class T1>
class auto_ptr
{
    template<class T2>
    auto_ptr<T1>& operator=(auto_ptr<T2>& Right) throw()()
    {   // assign compatible _Right (assume pointer)
        // 等号右边的auto_ptr,其ptr值传到左边的auto_ptr,原始值置为0
        T2* tmp = Right.ptr;
        Right.ptr = 0; 
        if (tmp != this.ptr)
            delete ptr;
        this.ptr = tmp;
        return (*this);
    }
}
复制代码

因为所有权的转移,所以auto_ptr不能用于STL容器的成员,在11标准之前,这真是悲剧——唯一的智能指针却几乎木有勇武之地~



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值