错误用法(自定义deleter时不能使用make_shared<>())
- std::shared_ptr
p_str = std::make_shared("name", - [](std::string *str) {
- std::cout << "delete: " << str << std::endl;
- delete str;
- });
正确用法
- std::shared_ptr
p_str(new std::string("name"), - [](std::string *str) {
- std::cout << "delete: " << *str << std::endl;
- delete str;
- });
std::default_delete只针对单个类对象,因此如果是数组,则需要指定deleter
- // 使用自定义deleter
- std::shared_ptr<int> p_arr(new int[10],
- [](int *arr) {
- std::cout << "delete array."<< std::endl;
- delete []arr;
- });
- // 使用缺省deleter
- std::shared_ptr<int> p_arr_a(new int[10], std::default_delete<int []>());
是 shared_ptr的帮手,用来共享对象但不拥有对象,它的use_count返回的是shared_ptr拥有的次数
可以解决类之间互相引用,而导致两者都不会被析构的场景
- std::shared_ptr
p_str_a = std::make_shared("nana"); - std::weak_ptr
p_str_w1 = p_str_a; - std::cout << "A expired:" << p_str_w1.expired() << std::endl;
- std::cout << "A use_count:" << p_str_w1.use_count() << std::endl;
- std::shared_ptr
p_str_a2 = p_str_a; - std::cout << "A expired:" << p_str_w1.expired() << std::endl;
- std::cout << "A use_count:" << p_str_w1.use_count() << std::endl;
- p_str_a.reset();
- p_str_a2.reset();
- std::cout << "B expired:" << p_str_w1.expired() << std::endl;
- std::cout << "B use_count:" << p_str_w1.use_count() << std::endl;
初始指针只能赋值一次给shared_ptr,之后的shared_ptr的初始化只能由其它shared_ptr初始化,防止重复析构。
错误示例:
- int *p_i = new int;
- std::shared_ptr<int> sp1_i(p_i);
- std::shared_ptr<int> sp2_i(p_i); // ERROR!!! 会产生两次析构
正确用法:
- int *p_i = new int;
- std::shared_ptr<int> sp1_i(p_i);
- std::shared_ptr<int> sp2_i(sp1_i);
为了解决对象内this指针多次被shared_ptr类声明时需要使用
示例:
- Class Data: std::enable_shared_from_this {
-
- std::shared get_share_ptr() {
-
- return std::shared_from_this();
- }
- }
类内使用 std::shared_from_this()函数即可获得this的shared_ptr。
- std::shared_ptr<void> sp(new int);
- std::static_pointer_cast<int *>(sp);
- // std::shared_ptr
g_int; - // {
- // std::shared_ptr
local_int = std::make_shared(10); - // std::atomic_store(&g_int, local_int);
- // }
- // 不允许复制语法赋初值
- // std::unique_ptr
tmp_i = new int; // ERROR - std::unique_ptr<int> tmp_i(new int); // OK
- std::unique_ptr<int> uptr;
- uptr.reset(new int); // 重置赋值
uptr.release(); // 释放使用权 uptr.reset() 或 uptr = nullptr;
- //方法1:
- if (uptr) {
- std::cout << "uptr = " << *uptr << std::endl;
- }
- //方法2: if (uptr != nullptr)
- //方法3: if (uptr.get() != nullptr)
- std::unique_ptr<int> up1(new int);
- // std::unique_ptr
up2(up1); // ERROR - std::unique_ptr<int> up2(std::move(up1));
unique_ptr作为函数参数:调用者必须手动调用std::move()
unique_ptr作为函数返回值:C++ 11编译器规定return语句不需要显式的调用std::move(),会自动调用std::move()
std::unique_ptr up_str(new std::string[10]) ;
- // 错误
- // std::unique_ptr
p_arr1(new int[10], - // [](int *arr) {
- // std::cout << "delete array."<< std::endl;
- // delete []arr;
- // });
- // 正确方法1
- std::unique_ptr<int,void(*)(int*)> p_arr2(new int[10],
- [](int *arr) {
- std::cout << "delete array2."<< std::endl;
- delete []arr;
- });
- // 正确方法2
- std::unique_ptr<int,std::function<void(int*)>> p_arr3(new int[10],
- [](int *arr) {
- std::cout << "delete array2."<< std::endl;
- delete []arr;
- });
- // 方法3
- auto fun_del = [](int *arr) {
- std::cout << "delete array2."<< std::endl;
- delete []arr;
- };
- // 方法4 利用alias
- using unique_ptr_int = std::unique_ptr<int, void(*)(int*)>;
- unique_ptr_int up_aa(new int[10], [](int *arr) {
- std::cout << "delete array2."<< std::endl;
- delete []arr;
- });
对于deleter,除了内存上的释放,还可以析构其它资源(如:文件句柄、socket句柄、共享内存等等)
示例如下:析构文件
- std::unique_ptr
void (*)(std::ofstream*)> p_ofs(new std::ofstream("text.txt"), - [](std::ofstream *ofs) {
- std::cout << "delete ofstream" << std::endl;
- ofs->close();
- delete ofs;
- });