当前位置: 代码网 > it编程>编程语言>C/C++ > C++实现shared_ptr共享指针的示例代码

C++实现shared_ptr共享指针的示例代码

2026年03月08日 C/C++ 我要评论
shared_ptr 图解一、什么是智能指针?智能指针 = 自动管理内存的指针// 传统指针的痛点int* p = new int(10);// ... 一堆代码delete p; // 万一忘了写

shared_ptr 图解

一、什么是智能指针?

智能指针 = 自动管理内存的指针

// 传统指针的痛点
int* p = new int(10);
// ... 一堆代码
delete p;  // 万一忘了写?内存泄漏!

// 智能指针的优雅
#include <memory>
shared_ptr<int> sp(new int(10));
// 不用写 delete!自动释放!

二、shared_ptr 核心特性

特性说明
共享所有权多个指针可指向同一对象
引用计数记录有多少指针在共享
自动释放最后一个指针销毁时,自动删除对象

三、创建 shared_ptr 的三种方式

1. 直接 new(不推荐)

shared_ptr<int> sp1(new int(100));        // 单个int
shared_ptr<int[]> sp2(new int[10]);        // int数组(c++17)

2. make_shared(✅ 推荐)

auto sp3 = make_shared<int>(100);          // 单个int,值100
auto sp4 = make_shared<string>("hello");   // string对象
auto sp5 = make_shared<vector<int>>();      // vector容器

3. 拷贝构造

auto sp6 = sp3;  // sp6 和 sp3 指向同一对象

四、引用计数:核心机制

auto sp = make_shared<int>(10);
cout << sp.use_count();  // 输出:1(只有sp自己)

auto sp2 = sp;           // 复制
cout << sp.use_count();  // 输出:2(sp和sp2共享)
cout << sp2.use_count(); // 输出:2

{
    auto sp3 = sp;       // 又复制一个
    cout << sp.use_count(); // 输出:3
}  // sp3 销毁,计数-1

cout << sp.use_count();  // 输出:2

sp2.reset();             // sp2 放弃指向
cout << sp.use_count();  // 输出:1

sp.reset();              // 最后一个也放弃
// 此时计数为0,对象被自动删除

计数变化图解

开始:sp ──→ [数据:10] 计数=1
sp2复制:sp ──→ [数据:10] ←── sp2 计数=2
sp3复制:sp ──→ [数据:10] ←── sp2 计数=3
                              ↑
                              sp3
sp3销毁:sp ──→ [数据:10] ←── sp2 计数=2
sp2.reset:sp ──→ [数据:10] 计数=1
sp.reset:对象被删除

五、常用操作详解

1. 解引用和成员访问

auto sp = make_shared<int>(10);
*sp = 20;                    // 修改值
cout << *sp;                  // 读取值

auto spstr = make_shared<string>("hello");
cout << spstr->size();        // 调用成员函数
(*spstr)[0] = 'h';            // 修改字符

2. 获取原始指针

auto sp = make_shared<int>(10);
int* raw = sp.get();          // 获取原始指针

// ⚠️ 警告:raw只是查看,不能删除!
// delete raw;                 // 千万不要!
// shared_ptr<int> sp2(raw);   // 千万不要!

3. 重置指针

auto sp = make_shared<int>(10);
sp.reset();                    // 放弃指向,计数-1

// 也可以重置并指向新对象
sp.reset(new int(20));         // 指向新int,原对象计数-1

4. 检查是否为空

auto sp = make_shared<int>(10);
if (sp) {                      // ✅ 简洁写法
    cout << "指针不为空";
}

if (sp.get() != nullptr) {      // ⚠️ 繁琐写法
    cout << "指针不为空";
}

六、自定义删除器

在需要特殊清理时使用:

// 方式1:普通函数
void deleteint(int* p) {
    cout << "自定义删除函数" << endl;
    delete p;
}
shared_ptr<int> sp1(new int(10), deleteint);

// 方式2:lambda表达式(推荐)
shared_ptr<int> sp2(new int(10), [](int* p) {
    cout << "lambda删除" << endl;
    delete p;
});

// 实际应用:管理文件句柄
shared_ptr<file> spfile(fopen("test.txt", "w"), 
    [](file* f) { 
        fclose(f); 
        cout << "文件已关闭" << endl;
    });

七、数组支持

// c++17 开始支持数组
shared_ptr<int[]> sparr(new int[100]);  // ✅
sparr[0] = 10;                           // 数组用 [] 访问

// 推荐写法
auto sparr2 = make_shared<int[]>(100);   // c++20

八、指向成员的特殊用法

struct person {
    string name;
    int age;
    double score;
};

auto p = make_shared<person>();

// 指向对象的某个成员,但共享整个对象的生命周期
shared_ptr<string> spname(p, &p->name);
shared_ptr<int> spage(p, &p->age);

cout << p.use_count();  // 输出:3(三个指针共享整个person)
// 即使 spname、spage 只指向成员,它们仍然控制整个对象的生命周期

九、常见错误(一定要记住!)

❌ 错误1:手动删除 get() 返回的指针

auto sp = make_shared<int>(10);
delete sp.get();  // 灾难!会重复删除导致崩溃

❌ 错误2:用原始指针创建多个 shared_ptr

int* p = new int(10);
shared_ptr<int> sp1(p);
shared_ptr<int> sp2(p);  // 灾难!两个独立管理同一内存
// 程序结束时两次 delete,崩溃!

❌ 错误3:循环引用(高级话题)

struct node {
    shared_ptr<node> next;
};
auto a = make_shared<node>();
auto b = make_shared<node>();
a->next = b;
b->next = a;  // 互相引用,都无法释放!
// 解决方案:用 weak_ptr

❌ 错误4:忘记数组语法

shared_ptr<int> sp(new int[10]);     // 错误!会调用 delete 不是 delete[]
shared_ptr<int[]> sp(new int[10]);   // 正确!

十、最佳实践总结

✅ 推荐这样做

// 1. 优先用 make_shared
auto sp = make_shared<int>(10);

// 2. 用 auto 简化代码
auto spvec = make_shared<vector<int>>();

// 3. 用 if(sp) 检查空指针
if (sp) { /* 使用 */ }

// 4. 需要特殊清理时用 lambda
auto spfile = shared_ptr<file>(fopen("a.txt", "r"), 
    [](file* f){ fclose(f); });

❌ 避免这样做

// 1. 滥用 get()
int* raw = sp.get();  // 除非必要

// 2. 手动管理引用计数
// 让系统自动处理就好

// 3. 混用原始指针和智能指针

十一、一句话记忆

shared_ptr 就像合租室友:有人搬进来计数+1,有人搬走计数-1,最后一个离开时负责打扫房间(删除对象)。你只需要安心住,不用操心打扫的事!

到此这篇关于c++实现shared_ptr共享指针的示例代码的文章就介绍到这了,更多相关c++ shared_ptr共享指针内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com