第十六章 - string类和标准类模板

一,智能指针模板

1.1,什么是智能指针?

智能指针是行为类似于指针的类对象,使用智能指针可帮助管理动态分配的内存与使用new创建的对象。

1.2,智能指针模板

C++中提供的智能指针模板有auto_ptr、unique_ptr、shared_ptr和weak_ptr。可以将new获得的地址赋给智能指针对象。当智能指针过期时,其析构函数将使用delete来释放内存。因此,如果将new返回的地址赋给智能指针对象,将无需记住稍后释放这些内存,当智能指针过期时,这些内存会自动被释放。智能指针对象的很多方面都类似于常规指针,例如,可以对它执行解除引用操作(*p)、访问结构成员(p->data)、将它赋给相同类型的智能指针。但是将智能指针对象赋值个另一个智能指针对象,将引发一些问题。

1.3,智能指针的应用

要创建智能指针对象,必须包含头文件memory。例如,模板auto_ptr包含如下构造函数

template<class X>
class auto_ptr{
public:
    explicit auto_ptr(X *p = 0) throw();
    ...
};

1,使用智能指针来管理动态分配的内存

下面是使用智能指针的例子

auto_ptr<int> pInt(new int);

下面是不使用智能指针的例子

int *p = new int;
...
delete p;

上面的指针变量p是一个普通的指针,当p的生命周期结束时,指针p分配的内存会被释放,但是p指向的内存空间不会被释放,因此,要手动调用delete,释放掉动态分配的内存空间。但pInt是一个智能指针,它是一个对象,当它的生命周期结束时,会调用它的析构函数,在析构函数中会释放掉动态分配的内存。

2,使用智能指针来管理用new创建的对象

class Resource{
public:
    Resource(){
        cout<<"object created."<<endl;
    }
    ~Resource(){
        cout<<"object delete."<<endl;
    }
};

int main(){
    auto_ptr<Resource> p1(new Resource);
    shared_ptr<Resource> p2(new Resource);
    unique_ptr<Resource> p3(new Resource);
}

输出结果

object created.
object delete.

object created.
object delete.


object created.
object delete.

Process returned 0 (0x0) execution time : 0.039 sPress any key to continue.

注意:

智能指针不能用来管理非堆内存,例如:

Resource res;
auto_ptr<Resource> p1(res);

p1过期时,程序将把delete运算符用于非堆内存,这是错误的。

1.4,智能指针赋值与复制操作带来的问题

(1),智能指针赋值带来的问题

auto_ptr<Resource> p1(new Resource);
auto_ptr<Resource> p2;
p2 = p1;

如果p1与p2是常规指针,则两个指针将指向同一个Resource对象。但是对于智能指针来说这是不能接受的,因为程序将试图删除同一个对象两次,一次是p1过期时,另一次是p2过期时。要避免这种问题,方法有多种:

  • 建立所有权概念:对于特定的对象,只能有一个智能指针可拥有它,这样只有拥有对象的智能指针的析构函数会删除该对象。然后,让赋值操作转让所有权。这就是用于auto_ptr与unique_ptr的策略,但unique_ptr的策略更加严格。
  • 使用引用计数:创建更高智能的指针,跟踪引用特定对象的智能指针数,这称为引用计数。例如,赋值时,引用计数加1,而指针过期时,计数将减1。仅当最后一个指针过期时,才调用delete,这是shared_ptr采用的策略。

(2),错误使用auto_ptr带来的问题

auto_ptr<string> p1(new string("hello world."));
auto_ptr<string> p2;
p2 = p1;
cout<<*p2<<endl;
cout<<*p1<<endl;

上面的程序在运行时会出错,出错的原因是,赋值语句p2 = p1将所有权从p1转到p2,这导致p1不再引用该字符串。在auto_ptr类型的指针放弃对象的所有权之后,便可能使用它来访问该对象,却发现这个智能指针是空的,所以会导致上面的问题。unique_ptr与auto_ptr都是采用所有权模型,如果用unique_ptr代替auto_ptr也会出错。但使用unique_ptr时,程序不会等到运行期崩溃,而在编译器发现赋值操作p2 = p1,将报错。

(3),使用shared_ptr代替auto_ptr解决上面的问题

shared_ptr<string> p1(new string("hello world."));
shared_ptr<string> p2;
p2 = p1;
cout<<*p2<<endl;
cout<<*p1<<endl;

上面的程序正常运行,这次p1与p2指向同一个对象,对象的引用计数由1增加到2。在程序末尾,p2的生命周期结束时,会调用它的析构函数,此时对象的引用计数降低为1。然后p1的生命周期结束,会调用它的析构函数,此时对象的引用计数降低为0,释放掉为对象分配的内存空间。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值