c++ 踩坑大法好 智能指针

1,智能指针是啥?

普通指针基本上就是一个变量,它的的生命周期和变量的作用域有关,局部变量在走出作用域以后就会销毁,全局变量可能程序运行完了就销毁了。

new出来的指针和普通指针的区别在于,new出来的那块内存区域是不会自动被释放的,需要你手动调用delete才能释放,然而由于种种原因,new----delete这俩节奏总是出状况,于是有人想到了自动回收的指针

智能指针根本上是一个class,你可以生成一个class实例用以管理一块内存,内存中放上你想放的东西,一方面该实例记录着该内存的地址,类型等信息,你可以和普通指针似的使用它,另一方面它记录对该内存的引用,当引用为0,就把该指针指向的内存区域释放出来。

2,shared_ptr共享指针:

1),基本语法

#include <stdarg.h>
#include <iostream>
#include <string>
#include <memory>    //shared_ptr
using namespace std;

int main(void)
{
    /*使用传入参数的方法生成智能指针*/
    shared_ptr<int> p1(new int);
    //创建一个int型的智能指针对象:在堆上创建两块内存,一个用于存储int,另一个用于记录对刚刚那块内存的引用的数量,初始化引用数量为1.
    //语法含义:shared_ptr是个模板类,使这个模板类按照int类型生成class类,然后创建p1对象,并且传递参数:new int,new int的意思是申请一个int大小的内存块,并且返回该内存块的地址。
    cout << p1.use_count() << endl;
    //检查p1所指向的内存块的引用计数,当前为1

    shared_ptr<int> p2 = p1;
    //创建新的智能指针p2也指p1指向的内存,这样的写法也可以:shared_ptr<int> p(p1)
    cout << p1.use_count() << endl;
    //现在引用数目为2

    p2.reset();
    //取消p2的指向,带参数的话p2会建立指向新内存
    cout << p1.use_count() << endl;
    //现在引用数目为1

    p2 = nullptr;
    //把p2重置为nullptr(这大约是空指针约定俗成的写法,暂不讨论)
    if (p2 == nullptr) {
        printf("empty ptr\n");
    }

    /*使用构造函数来创建智能指针,推荐使用这种方法*/
    shared_ptr<int> p3 = std::make_shared<int>();
    //语法含义:int型智能指针shared_ptr的类实例p1的地址是什么呢?是模板函数make_shared根据int类型生成的存值内存的地址,当然它还同时生成了存储引用的内存


    //有人说使用智能指针存储数组会有问题,因为数组释放内存需要用delete [] ptr;而不是delete ptr;需要重写析构方法
    //不清楚内部机制以及看不懂源码的我,最后决定不用智能指针存储数组,问题暂时放着吧
    /*以下是错误示范,虽然也能跑*/
    shared_ptr<int[10]> p4 = std::make_shared<int[10]>();
    cout <<"array1:"<< p4.use_count() << endl;
    p4.reset();
    cout <<"array2:"<< p4.use_count() << endl;

    return 0;
}

2),如何从智能指针中获取数据?

#include <stdarg.h>
#include <iostream>
#include <string>
#include <memory>    //shared_ptr
#include <vector>
using namespace std;

int main(void)
{
    /*普通的vector的使用:*/

    vector<int> hehe = { 4,5 };
    vector<int> hehe1 = vector<int>(2,4);
    //生成一个内容是两个4的int的普通vector
    hehe1.push_back(4);
    //普通vector追加数据
    for (auto itt : hehe1)
    {
        printf("orign:%d\n", itt);
    }

    /*智能指针指向的vector怎么用?*/

    shared_ptr < vector<int > > vi0(new vector<int>);
    //声明一个智能指针指向int的vector
    vi0->push_back(1);
    vi0->push_back(2);
    //智能指针vector追加数据,1和2,注意操作符是这样的:->
    for (auto itt : (*vi0))
    {
        printf("shared_ptr:%d\n", itt);
    }

    //shared_ptr < vector<int > > vi = make_shared<vector<int >>(hehe);
    shared_ptr < vector<int > > vi = make_shared<vector<int >>(2,3);
    //使用构造函数声明并且初始化一个智能指针指向int的vector,内容是两个3
    int len1 = (*vi).size();
    int len2 = vi->size();
    //两种方法获取vector长度,一个是使用*翻译智能指针,另一个是使用:->
    printf("len1:%d,len2:%d\n",len1, len2);

    printf("use count1:%d\n", vi.use_count());
    //智能指针本来只有一个引用
    vector<int> *test = vi.get();
    //据说是让智能指针返会一个普通指针,
    printf("use count2:%d\n", vi.use_count());
    //看来get()方式并不能让智能指针引用增加,现在它还是只有一个引用

    printf("address of test:%p\n", test);
    //vi销毁以前查看一下test地址
    vi = nullptr;
    //智能指针销毁
    printf("use count3:%d\n", vi.use_count());
    //现在引用为0,确实销毁了
    printf("address of test:%p\n", test);
    //销毁以后地址还是指向那块内存,test的地址没有改变
    printf("len of test : %d\n", (*test).size());
    //但是已经不能获取到长度,应该是已经没法使用或者地址上全都填充0了,返回0

    *test= vector<int>(2, 4);
    //但是依旧可以在那块内存上进行操作,比如重新赋值
    printf("len of test : %d\n", (*test).size());
    //可以获取长度,2
    for (auto itt : (*test))
    {
        printf("test:%d\n", itt);
    }
    //可遍历

    return 0;
}

原文链接: https://www.cnblogs.com/0-lingdu/p/12327136.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/195567

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月12日 下午7:01
下一篇 2023年2月12日 下午7:01

相关推荐