一、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>());
std::static_pointer_cast<DerivedClass>(ptr_to_base)->f();
static_cast<DerivedClass*>(ptr_to_base.get())->f();
}
输出:
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++手册来自学了,已经有能力去看懂和分析上面的东西了!
注:本文章参考了《朱老师物联网大讲堂》课程笔记,并结合了自己的实际开发经历以及网上他人的技术文章,综合整理得到。如有侵权,联系删除!水平有限,欢迎各位在评论区交流。
|