当前位置:   article > 正文

c++ primer plus 第16章string 类和标准模板库,16.2.1 使用智能指针

c++ primer plus 第16章string 类和标准模板库,16.2.1 使用智能指针

c++ primer plus 第16章string 类和标准模板库,16.2.1 使用智能指针

c++ primer plus 第16章string 类和标准模板库,16.2.1 使用智能指针


16.2.1 使用智能指针

这三个智能指针模板(auto ptr、unique ptr 和 shared ptr)都定义了类似指针的对象,可以将 new 获得(直接或间接)的地址赋给这种对象。当智能指针过期时,其析构函数将使用delete来释放内存。因此,如果将new 返回的地址赋给这些对象,将无需记住稍后释放这些内存:在智能指针过期时,这些内存将自动被释放。图 16.2说明了 auto ptr 和常规指针在行为方面的差别;share ptr 和 unique ptr 的行为与 auto ptr 相同。
在这里插入图片描述

要创建智能指针对象,必须包含头文件memory,该文件模板定义。然后使用通常的模板语法来实例化所需类型的指针。例如,模板 auto ptr 包含如下构造函数:

template<class X>class auto ptr{
public:
explicit auto ptr(X*p=0)throw();
...}
  • 1
  • 2
  • 3
  • 4

本书前面说过,throw()意味着构造函数不会引发异常:与autoptr 一样,throw()也被摒弃。因此,请求X类型的 auto ptr将获得一个指向X类型的 auto ptr:

auto ptr<double> pd(new double);//pd an auto ptr to double
								//(use in place of double * pd)
auto ptr<string>ps(new string);//ps an auto ptr to string
								//(use in place of string *ps)
  • 1
  • 2
  • 3
  • 4

new double 是 new 返回的指针,指向新分配的内存块。它是构造函数 auto ptr的参数,即对应于原型中形参p的实参。同样,newstring也是构造函数的实参。其他两种智能指针使用同样的语法:

unique_ptr<double>pdu(new double); // pdu an unique ptr to double
shared_ptr<string>pss(new string);//pss a shared ptr to string
  • 1
  • 2

因此,要转换remodel()函数,应按下面3个步骤进行:

  • 1.包含头文件 memory;
  • 2.将指向 string 的指针替换为指向 string 的智能指针对象;
  • 3.删除 delete 语句。
    下面是使用auto ptr修改该函数的结果:
#include <memory>
void remodel(std::string & str)
std::auto ptr<std::string>ps(new std::string(str));
...
if (weird thing())
 throw exception();
str = *pS;
//delete ps;NO LONGER NEEDED
return;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

注意到智能指针模板位于名称空间 std中。程序清单16.5是一个简单的程序,演示了如何使用全部三种智能指针。要编译该程序,您的编译器必须支持C++11新增的类share ptr和 unique ptr。每个智能指针都放在一个代码块内,这样离开代码块时,指针将过期。Report 类使用方法报告对象的创建和销毁。

程序清单16.5 smrtptrs.cpp

// smrtptrs.cpp -- using three kinds of smart pointers
#include <iostream>
#include <string>
#include <memory>

class Report
{
private:
    std::string str;
public:
    Report(const std::string s) : str(s) { std::cout << "Object created!\n"; }
    ~Report() { std::cout << "Object deleted!\n"; }
    void comment() const { std::cout << str << "\n"; }
};

int main()
{
    {
        std::auto_ptr<Report> ps (new Report("using auto_ptr"));
        ps->comment();   // use -> to invoke a member function
    }
    {
        std::shared_ptr<Report> ps (new Report("using shared_ptr"));
        ps->comment();
    }
    {
        std::unique_ptr<Report> ps (new Report("using unique_ptr"));
        ps->comment();
    }
    // std::cin.get();  
    return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

所有智能指针类都一个explicit 构造函数,该构造函数将指针作为参数。因此不需要自动将指针转换为智能指针对象:

shared_ptr<double> pd;
double *p_reg =new double;
pd =p_reg;
//not allowed(implicit conversion)
//allowed(explicit conversion
pd =shared_ptr<double>(p_reg);
shared_ptr<double>pshared = p_reg;// not allowed(implicit conversion)
shared_ptr<double>pshared(preg);//allowed(explicit conversion)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

由于智能指针模板类的定义方式,智能指针对象的很多方面都类似于常规指针。例如,如果 ps 是一个智能指针对象,则可以对它执行解除引用操作(*ps)、用它来访问结构成员(ps->puMIndex)、将它赋给指向相同类型的常规指针。还可以将智能指针对象赋给另一个同类型的智能指针对象,但将引起一个问题,这将在下一节进行讨论。
但在此之前,先说说对全部三种智能指针都应避免的一点:

string vacation("I wandered lonely as a cloud.");
shared_ptr<string>pvac(&vacation);//NO!
  • 1
  • 2

pvac 过期时,程序将把delete运算符用于非堆内存,这是错误的。
就程序清单 16.5演示的情况而言,三种智能指针都能满足要求,但情况并非总是这样简单。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/853843
推荐阅读
相关标签
  

闽ICP备14008679号