智能指针与STL查漏补缺(2)

一、CPP11最常用的智能指针shared_ptr

学习参考:https://zh.cppreference.com/w/cpp/memory/shared_ptr

1、shared_ptr的设计思路

(1)auto_ptr和unique_ptr是独占式智能指针,即任何时候智能指针和对象是1对1绑定的,不能2对1

(2)shared_ptr是基于引用计数式的设计,因此可以多个智能指针绑定1个对象(普通指针就是这样的,可以多个指针指向一个对象),这会带来很多方便

(3)shared_ptr在基础的定义和使用方式上,与前2个很类似,所以很容易学会使用

2、shared_ptr的基本使用

在这里插入图片描述
(1)智能指针的创建,一般有2种方式:使用构造函数、使用std::make_shared方法

(2)代码实战:shared_ptr与单个对象的绑定和使用,测试智能指针的多种常见用途

#include <iostream>
#include <memory>

using namespace std;

struct Foo
{
    Foo(){cout << "Foo()" << endl;};
    ~Foo(){cout << "~Foo()" << endl;};
};

struct D
{
    void operator()(Foo* p) const
    {
        cout << "Call  delete from function object..." << endl;
        delete p;
    }
};

int main(int argc, char *argv[])
{
    {
        cout << "constructor with no managed object" << endl;
        shared_ptr<Foo> sh1;
    }

    {
        cout << "constructor with object" << endl;
        shared_ptr<Foo> sh2(new Foo);
        shared_ptr<Foo> sh3(sh2);
        cout << sh2.use_count() << endl;
        cout << sh3.use_count() << endl;
    }

    {
        cout << "constructor with object and deleter" << endl;
        shared_ptr<Foo> sh4(new Foo, D());
        shared_ptr<Foo> sh5(new Foo,[](auto p){cout << "Call delete from lamba" << endl; delete p;});
    }

    return 0;
}

二、shared_ptr的引用计数详解

1、引用计数的获取和检测

(1)use_count
(2)unique
(3)operator bool
(4)reset
在这里插入图片描述

#include <iostream>
#include <memory>
#include <type_traits>

using namespace std;

class C
{
public:
    C(){};
    C(int i):i(i){};
    int i;
};

int main(int argc, char *argv[])
{
    auto sp = make_shared<C>();
    static_assert(is_same<decltype(sp), shared_ptr<C>>::value, "false");//静态断言,编译时起作用
    cout << sp.unique() << endl;
    cout << sp.use_count() << endl;

    return 0;
}

2、引用计数实现智能指针的总结

(1)基本原理仍然是释放智能指针对象时,调用其Deleter,再调用被绑定对象的析构来释放

(2)auto_ptr和unique_ptr都被实现为独占式,所以在=时必然发生占有权转移

(3)shared_ptr增加引用计数,好处是可以让多个智能指针对象,同时绑定一个被管理对象,本质上其实是避免了被管理对象被多次自动释放带来的错误,所以比unique_ptr更好用

3、shared_ptr的其他细节

(1)static_pointer_cast(静态类型强制转换)/dynamic_pointer_cast(动态强制类型转换)

参考学习:https://zh.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast

(2)特化的原子操作(期望对复杂的结构进行无锁操作,而不用担心GC (垃圾回收机制)/内存泄漏)

#include <iostream>
#include <memory>
 
struct BaseClass {};
 
struct DerivedClass : BaseClass
{
    void f() const
    {
        std::cout << "Hello World!\n";
    }
    ~DerivedClass(){ // 注意:它不是虚的
        std::cout << "~DerivedClass\n";
    }
};
 
int main()
{
    std::shared_ptr<BaseClass> ptr_to_base(std::make_shared<DerivedClass>());
 
    // ptr_to_base->f(); // 错误不会编译: BaseClass 无名为 'f' 的成员
 
    std::static_pointer_cast<DerivedClass>(ptr_to_base)->f(); // OK
    // (构造临时 shared_ptr ,然后调用 operator-> )
 
    static_cast<DerivedClass*>(ptr_to_base.get())->f(); // 亦 OK
    // (直接转型,不构造临时 shared_ptr )
}

输出:
Hello World!
Hello World!
~DerivedClass

三、weak_ptr与shared_ptr的关联和使用

参考学习:
https://blog.csdn.net/albertsh/article/details/82286999(必看)
https://zh.cppreference.com/w/cpp/memory/weak_ptr

四、迭代器适配器

参考学习:
http://c.biancheng.net/view/7255.html
https://zh.cppreference.com/w/cpp/iterator
在这里插入图片描述

五、function封装器和可变参数模版

1、function封装器

参考学习:https://blog.csdn.net/gongjianbo1992/article/details/105160627/

2、可变参数模版

参考学习:https://blog.csdn.net/xiaohu2022/article/details/69076281

3、C++系列文章前3部分总结

(1)C++课程前3部分(从C到C++,C++和面向对象,STL和泛型编程)是主体,后2部分是扩展。

(2)前3部分学完,即可使用C++去做事,譬如GUI的qt、譬如AI的opencv

(3)后2部分是C++编程功底和优化、更深度理解C++的,建议有一定C++使用体验后再去学

(4)博客文章更新上也会先暂停C++去更新一些其他东西(海思专题、设备树、python视觉方面相关的),后面再找时间来继续学习并更新,其实大家有了前面的基础,完全可以尝试自己去啃那个C++手册来自学了,已经有能力去看懂和分析上面的东西了!

注:本文章参考了《朱老师物联网大讲堂》课程笔记,并结合了自己的实际开发经历以及网上他人的技术文章,综合整理得到。如有侵权,联系删除!水平有限,欢迎各位在评论区交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小嵌同学

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

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

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

打赏作者

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

抵扣说明:

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

余额充值