C++智能指针

概念:在C++11中通过引入智能指针,不需要手动释放内存

分类:

  • std::unique_ptr

  • std::shared_ptr

  • std::weak_ptr

一、智能指针概述

智能指针是原始指针的封装,优点是会自动分配内存,不用担心潜在的内存泄漏。

只能解决一部分问题,即独占、共享所有权指针的释放、传输

没有从根本上解决C++ 内存安全问题,不加以注意依然会造成内存安全问题。

二、独占指针unique_ptr

1、概念

unique_ptr:在任何给定的时刻,只能有一个指针管理内存。

当指针超出作用域时,内存将自动释放

该类型指针不可以copy,只可以move

2、创建方式:
  • 通过已有裸指针创建

  • 通过new 创建

  • 通过 std::make_unique 创建(推荐)

// 使用unique pointer 会更安全
    Cat *c_p2 = new Cat("nnnnn");
    unique_ptr <Cat> u_c_p1{c_p2}; // u_c_p1指针名
//    c_p2->cat_info();
//    u_c_p1->cat_info();
//    // 当c_p2 改变值的时候,u_c_p1也会随着改变
//    c_p2->set_cat_name("enenne");
//    u_c_p1->cat_info();
    /*
     constructor of cat:nnnnn
     cat info name:nnnnn
     cat info name:nnnnn
     cat info name:enenne
     destructor of cat:enenne*/
    cout << "----------" << endl;
    //delete c_p2;
    c_p2 = nullptr;
    u_c_p1->cat_info();
    cout << "----第二种------" << endl;
    //第二种  new
    unique_ptr <Cat> u_c_p3{new Cat("dd")};
    u_c_p3->cat_info();
    u_c_p3->set_cat_name("ooooo");
    u_c_p3->cat_info();


    cout << "----第san种------" << endl;
    // 第三种 make
    unique_ptr<Cat> u_c_p4 = make_unique<Cat>("123");
    u_c_p4->cat_info();
    u_c_p4->set_cat_name("pppp");
    u_c_p4->cat_info();
3、使用
  • 可以通过 get()获取地址

  • 可以通过 → 调用成员函数

  • 可以通过 * 调用 dereferencing

    cout << "----get 方法------" << endl;
    // 使用get方法
    unique_ptr <int> u_c_1 {new int(5)};
    unique_ptr <int> u_c_2 = make_unique <int>(4);
    cout << "u_c_1 的地址为:" << u_c_1.get() << endl;
    cout << "u_c_2 的地址为:" << u_c_2.get() << endl;

    cout << *u_c_1 << endl;

三、unique_ptr 与函数调用

unique_ptr 不可以copy,值可以move

在做函数参数或是返回值中一定要注意所有权问题。

注意事项:
  • passing by value:需要用move转移内存拥有权,如果参数直接传入make_unique 语句,自动转换为move

  • passing by reference:如果设置参数为const则不能改变指向,比如reset(),reset()为智能指针清空方法

  • return by value:指向一个local object ,可以用作链式函数

void do_with_cat_pass_value(unique_ptr<Cat> c){
    c->cat_info();
}
void do_with_cat_pass_refer(const unique_ptr<Cat> &c){  // 建议
    c->cat_info();
    c->set_cat_name("jjjjjjj");
    c->cat_info();
    //c.reset();  // 清空指针
}
unique_ptr<Cat> get_unique_ptr(){
    unique_ptr <Cat> u = make_unique<Cat> ("9898");
    return u;
}


    cout << "----函数调用------" << endl;

    // 独占指针与函数调用
    // 1、pass by value
    unique_ptr <Cat> u1 = make_unique<Cat>("dd");
    do_with_cat_pass_value(move(u1));   // 必须要加move
    // u1->cat_info();   不能执行
    //do_with_cat_pass_value(unique_ptr<Cat>());


    // 2、pass by reference
    unique_ptr <Cat> u2 = make_unique<Cat>("popo");
    do_with_cat_pass_refer(u2);
    cout << u2.get() << endl;

    //3、返回
    get_unique_ptr()->cat_info();

四、计数指针:shared_ptr

shared_ptr :计数指针又称为共享指针

与unique_ptr 不同,计数指针可以共享数据

  • shared_ptr 创建了一个计数器与类对象所指的内存相关联

  • copy 则计数器加1,销毁则计数器减一

  • qpi 为use_count()

cout << "----计数指针------" << endl;
    // 计数指针 shared_ptr
    // 常量类型
    shared_ptr <int> s1 = make_shared<int>(6);
    cout << "value:" << *s1 << endl;//value:6
    cout << s1.use_count() << endl;  // 1,计数器个数

    // 进行copy 操作
    shared_ptr<int> s2 = s1;
    cout << *s2 << endl;  //6
    cout << s2.use_count() << endl;  //2
    cout << s1.use_count() << endl;  //2

    *s2 = 90;
    cout << "s2 的值为:" << *s2 << endl;
    cout << "s1 的值为:" << *s1 << endl;
    shared_ptr<int> s3 = s1;

    s2 = nullptr;
    cout << "s3 的use count为:" <<s3.use_count() << endl;  //2
    cout << "s2 的use count为:" <<s2.use_count() << endl;  //0
    cout << "s1 的use count为:" <<s1.use_count() << endl;  //2


    cout << "---自定义数据类型------" << endl;
    // 自定义类型
    shared_ptr <Cat> ss1 = make_shared<Cat>("dsds");
    cout << "cat shared_ptr use count:" << ss1.use_count() << endl;

    shared_ptr <Cat> ss2 = ss1;
    shared_ptr <Cat> ss3 = ss1;
    cout << "cat ss1 shared_ptr use count:" << ss1.use_count() << endl;  //3
    cout << "cat ss2 shared_ptr use count:" << ss2.use_count() << endl;  //3
    cout << "cat ss3 shared_ptr use count:" << ss3.use_count() << endl;  //3

    ss1.reset();
    cout << "cat ss1 shared_ptr use count:" << ss1.use_count() << endl;  //0
    cout << "cat ss2 shared_ptr use count:" << ss2.use_count() << endl;  //2
    cout << "cat ss3 shared_ptr use count:" << ss3.use_count() << endl;  //2



    cout << "---自定义数据类型------" << endl;

五、shared_ptr 与函数

  • shared by passed by value:copy ,函数内部计数器加以

  • shared_ptr passed by ref:const 表示不可改变指向

  • returning by value:链式调用

// 计数指针
void cat_by_value(shared_ptr <Cat> cat){
    cout << cat->getName() << endl;
    cout << "func use count :" << cat.use_count() << endl;
    cat->set_cat_name("oooo");
    cat->cat_info();
}
void cat_by_ferer(shared_ptr <Cat> &cat){
    cout << cat->getName() << endl;
    cout << "func use count :" << cat.use_count() << endl;
    cat->set_cat_name("lsjf");
    cat->cat_info();
}
shared_ptr <Cat> get_shared_ptr(){
    shared_ptr<Cat> rePtr = make_shared<Cat>("sdfjklsadklf");
    return rePtr;
}


    cout << "---计数指针和函数------" << endl;
    shared_ptr <Cat> sh1 = make_shared<Cat> ("jishujishu ") ;
    cat_by_value(sh1);
    cout << "sh1 use count :" << sh1.use_count() << endl;
    sh1->cat_info();

    cat_by_ferer(sh1);
    sh1->cat_info();

    shared_ptr<Cat> sh2 = get_shared_ptr();
    sh2->cat_info();

 // 链式
    get_shared_ptr()->cat_info();



    cout << "---计数指针和函数------" << endl;
    /*
     func use count :2
     sh1 use count :1
     */

六、sharedptr 与 uniqueptr 的转化

  • attention:不能将sharedptr 转换成uniquestr

  • uniqueptr 可以转换成sharedptr : 通过move 方法

  • 将函数返回值设为uniqueptr 是一种常见的形式,可以提高代码的复用性,可以随时改变为sharedptr

unique_ptr<Cat> get_unique_ptr(){
    unique_ptr <Cat> u = make_unique<Cat> ("local cat");
    return u;
}

cout << "---独占指针和计数指针的转换------" << endl;
    unique_ptr <Cat> m1 = make_unique<Cat>("didi");
    shared_ptr <Cat> m2 = move(m1); // 转换之后m1 指针不可用
    cout << "m2 use count:"<< m2.use_count() << endl;

    //返回
    shared_ptr<Cat> m3 = get_unique_ptr();  // 直接将unique 指针转换成 shared 指针
    if(m3){
        m3->cat_info();
        cout << "m3 的 use count:" << m3.use_count() << endl;
    }

七、weakptr : sharedptr 的补充

1、weak_ptr :
  • 不拥有 所有权

  • 并不能调用 → 和 解引用 *

2、作用

如果有一个A类,其中有一个需求需要存储其他A类对象的信息,如果使用shared——ptr ,在销毁时,会遇到循环依赖问题,所以需要一个不需要拥有所有权的指针来标记该同类对象。

3、转换

weakptr 可以通过 lock()函数提升为 sharedptr (类型转换)

  cout << "---weak_ptr------" << endl;
    shared_ptr<Cat> w1 = make_shared<Cat>("w1");
    weak_ptr w2 (w1); // weakptr 不可以单独存在,只能依靠shared指针

    // w 2 可以调用use count ,但是计数器不会加1
    cout << "w1 use count:" << w1.use_count() << endl;
    cout << "w2 use count:" << w2.use_count() << endl;
    /*
     w1 use count:1
     w2 use count:1*/

    //w2->cat_info();  报错,不能进行调用
    //cout << *w2 << endl;   报错,不能进行接引用

    shared_ptr w3 = w2.lock();  // 转换成shared_ptr
    cout << "w1 use count:" << w1.use_count() << endl;
    cout << "w2 use count:" << w2.use_count() << endl;
    cout << "w3 use count:" << w3.use_count() << endl;
    /*
     w1 use count:2
     w2 use count:2
     w3 use count:2
    */
  • 8
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱空nnnn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值