C++ 常规指针与智能指针模板类基础知识

本文章所有内容源于《C++Primer Plus第六版》16.2节,帮您快速理解使用智能指针


常规指针基础知识:

指针的作用:在写代码调用大量数据的时候,如果将整个数据块拿过来用,这样十分耗费内存与运行时间。指针调用需要的数据块内存首地址即可,只要知道了该内存首地址,就可以访问整个内存块以及它上面的数据。

堆区:在使用指针的时候,程序员需要在堆区,使用“new创建一个堆并占据内存,并在指针使用结束后,使用“delete删除占用的内存空间。

#include <iostream>
#include <string>
#include <memory>
using namespace std;
//常规指针
class Report
{
private:
    int number;
public:
    Report()
    {
        cout << "构造函数!" << endl;
        number = 5;
    }
    ~Report()
    {
        cout << "析构函数!" << endl;
    }
    void test( ) 
    {
        cout << number << endl;
    }
};

int main()
{
    cout << "常规数据指针:" << endl;
    int* p = new int ;
    *p = 500;
    cout << "*p = " << *p << endl;
    cout << p << endl;
    delete p;
    cout << "-------------------------------------"<< endl;

    cout << "常规类指针:" << endl;
    Report* m = new Report;
    cout << "number = "  ;
    m->test();
    cout << m << endl;
    delete m;
    return 0;
}

上述代码展示了指针在使用时的基础用法,一个是指向一个数,另一个是指向一个类。需要记住的是:

  1. 指针的定义方法:
类型* 名称 = new 类型;

这里的类型肯能是int、double,也可能是创建的类。

  1. 指针释放:
delete 名称;

指针如果不释放就会一直占用堆区内存空间,当堆区内存满了,程序就会崩溃,所以使用结束后必须释放指针。
可是问题就在于在维护大段代码时,经常会用到指针间的互相调用。如果手动释放指针,可能会出现:把指针A释放了,结果一开始被指针A赋值的指针B不能用了。因此我们引出智能指针的概念。

  1. 地址:

指针指向的是地址,代码中p就是内存中的地址,*p成为解引用指向该地址代表的数据

cout << p << endl;

智能指针基础知识:

智能指针作用:类似于指针的类对象,简单说就是在既可以动态分配内存(在堆区new内存),也可以在代码块(一个“{}”)结束后,自动释放内存。就不再需要程序员手动对指针进行释放,防止内存泄漏。

分类:shared_ptr、unique_ptr、auto_ptr

#include <iostream>
#include <string>
#include <memory>
using namespace std;
//智能指针模板类
class Report
{
private:
    std::string str;
public:
    Report( const std::string s ) : str(s)
    {
        std::cout << " Object created! \n " ;
    }
    ~Report()
    {
        std::cout << "Object delected! \n" ;
    }
    void comment() const
    {
        std::cout << str << "\n" ; //常成员函数是指不能改变成员变量值的函数
    }
};

int main()
{
    {
    std::auto_ptr<Report> ps ( new Report("using auto_ptr") );
    ps->comment();
    }
    cout << "--------------------------"<<endl;
    {
    std::unique_ptr<Report> ps( new Report("using shared_ptr") );
    ps->comment();
    }
    cout << "--------------------------"<<endl;
    {
    std::shared_ptr<Report> ps( new Report("using shared_ptr") );
    ps->comment();
    }

    cout << "--------------------------"<<endl;
    {
std::shared_ptr<Report> pt = std::shared_ptr<Report> ( new Report("shared_ptr") );
    pt->comment();
    }
   cout << "--------------------------"<<endl;
    return 0;
}

上述代码首先创建一个Report类,定义它的构造函数、析构函数,定义一个comment函数用于接收构造函数的字符串常量(为了便于观察)。接着在main函数中使用了三种智能指针模板类。需要记住的是:

  1. 智能指针定义方法:
std::智能指针类型<类型> 名称( new 构造函数 )

智能指针类型就是:shared_ptr、unique_ptr、auto_ptr
类型:类名
名称:自己创建,常用Ptr

  1. 智能指针调用:
名称->成员函数;

成员函数在类中定义,注意指针的使用时候成员函数使用“->”。
(没有指针时,成员函数调用为“名称.成员函数”)

  1. 智能指针赋值:
std::智能指针类型<类型> 名称 = std::智能指针类型<类型> (new 构造函数);

举两个个例子:
对于类:

std::shared_ptr<Report> pt = std::shared_ptr<Report> ( new Report("shared_ptr") );

对于string:

    std::shared_ptr <string> films[5] = 
    {
        shared_ptr<string> (new string ("Fowl Balls")),
        shared_ptr<string> (new string ("Duck Walls")),
        shared_ptr<string>(new string("Chicken Runs")),
		shared_ptr<string>(new string("Turkey Errors")),
		shared_ptr<string>(new string("Goose Eggs"))
    }

智能指针使用问题:

博主在学习《视觉slam十四讲》时遇到的全都是shared_ptr,所以可想它的地位。

在使用智能指针的时候,也会出现一个智能指针的数据赋值给另一个智能指针,这里我们指类型不变,例如(unique_ptr类型的智能指针赋值给unique_ptr类型的智能指针),直接上例子:

#include <iostream>
#include <string>
#include <memory>
using namespace std;
//该文件用于证明auto_ptr不是一个好的选择

int main()
{
    //unique_ptr
    std::unique_ptr <string> films[5] = 
    {
        unique_ptr<string> (new string ("Fowl Balls")),
        unique_ptr<string> (new string ("Duck Walls")),
        unique_ptr<string>(new string("Chicken Runs")),
		unique_ptr<string>(new string("Turkey Errors")),
		unique_ptr<string>(new string("Goose Eggs"))

    }; 
    unique_ptr<string> pwin;
    pwin = films[2];//films[2]失去所有权

    /*
    //auto_ptr
    std::auto_ptr <string> films[5] = 
    {
        auto_ptr<string> (new string ("Fowl Balls")),
        auto_ptr<string> (new string ("Duck Walls")),
        auto_ptr<string>(new string("Chicken Runs")),
		auto_ptr<string>(new string("Turkey Errors")),
		auto_ptr<string>(new string("Goose Eggs"))

    }; 
    auto_ptr<string> pwin;
    pwin = films[2];//films[2]失去所有权
    */

     /*
   //shared_ptr 唯一能用
    std::shared_ptr <string> films[5] = 
    {
        shared_ptr<string> (new string ("Fowl Balls")),
        shared_ptr<string> (new string ("Duck Walls")),
        shared_ptr<string>(new string("Chicken Runs")),
		shared_ptr<string>(new string("Turkey Errors")),
		shared_ptr<string>(new string("Goose Eggs"))

    }; 
    shared_ptr<string> pwin;
    pwin = films[2];//films[2]失去所有权
    */

    cout << "最佳鸟类棒球电影的提名者是:"<<endl;
    for ( int i = 0 ; i < 5 ; i++ )
    {
        cout << *films[i] << endl;  //指针所以要解引用
    }
    cout << "获胜者是:" << *pwin <<endl;

    return 0;
}

将代码运行会报错,问题出在当使用unique_ptr时,films[2]已经被提出来给了pwin,那么film[2]现在就是个空指针,所以无法运行。读者可以取消其他的注释,尝试用shared_ptr或者auto_ptr,最终发现只有shared_ptr可以正常跑通过。

注意:

  1. shared_ptr在赋值使用后,指针计数器从1变成了2,读者可以理解为系统知道你又指向了一个和它一样的数据,那么在释放的时候,从2至1挨个释放(即1->2->1->0)。而另外两种在赋值时,指针计数器始终为1,可以理解为第一个数据块指针从1变成了0,没了,然后新赋值的指针从0变成了1(即1->0,0->1->0)。
  2. 使用new分配内存时,才能使用auto_ptr和shared_ptr,使用new []分配内存,不能使用它们。不是用new分配内存时,不能使用auto_ptr或shared_ptr;不是用new或new []分配内存时,不能使用unique_ptr。
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值