C++智能指针shared_ptr使用实例

本文介绍了C++中智能指针shared_ptr的作用及使用方法。通过对比new/delete的操作,解释了shared_ptr如何帮助解决内存管理和防止内存泄漏的问题。同时提供了具体的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

被new/delete折磨过之后,才能真正体会智能指针有多好用。

智能指针是用于管理指针的类。
其中shared_ptr是专门管理那些可能被多个地方用到的指针的类。

C++11中智能指针的头文件是:

#include <memory>

shared_ptr有什么用?

我们知道new和delete是需要一一对应的。
但是,有太多的情况诱惑我们一不小心就将一个指针“到处散”了。
这下基本就已经注定new和delete无法一一对应了。要么,没有delete,导致内存泄漏;要么,多个地方delete了,导致重复释放(一般报错:“段错误”、“bad access”之类)。
讽刺的是,诱惑我们将一个指针到处散的可能是“为了节省内存”(避免“重复”创建类似的对象)

shared_ptr就是为了解决这个问题:
一坨空间大家用,没人用了就释放。

shared_ptr将相当于这坨空间的“管家”,大家都可以用这坨空间,而且大家无需考虑在用完这坨空间之后要不要释放。因为,没人在使用这坨空间时,“管家”会将这坨空间释放。

shared_ptr怎么用?

指针是怎么用的?

1int* a = new int(1);
2, int* func(int* b){}

从代码上看,只需要做两处替换:

shared_ptr<int>”替换“int*”
“make_shared<int>”替换“new int

然后就可以像一般使用指针那样进行操作了。


如上“两处替换”代码举例如下:

std::shared_ptr<Cone> CreateConeShape() {

    /*此处省略若干行*/
    return std::make_shared<Cone>(o2w, w2o, reverseOrientation, height, radius, phimax);
}
shared_ptr<Grid> Robot = make_shared<Grid>(make_shared<Mesh>());
inline void
FM_SV_GlossySpecular::set_cs(shared_ptr<Texture> t_ptr) {
    cs = t_ptr;
}

参考链接:
1,(基本介绍)
https://blog.youkuaiyun.com/qq_35116353/article/details/68957414
2,(容易犯的错误)
http://www.cnblogs.com/heleifz/p/shared-principle-application.html

### C++ 中 `std::shared_ptr` 的使用方法与解析 #### 1. 定义与基本功能 `std::shared_ptr` 是一种智能指针,属于 C++ 标准库 `<memory>` 头文件的一部分。它的主要作用是通过引用计数机制实现动态分配对象的自动管理[^2]。 - **所有权共享**:多个 `std::shared_ptr` 可以共同指向同一对象,每个实例都对该对象拥有一部分所有权。 - **控制块**:内部维护了一个控制块,记录当前对象的引用计数。当引用计数降为零时,对象会被自动释放并清理内存。 #### 2. 创建方式 以下是创建 `std::shared_ptr` 的常见方法: ```cpp #include <iostream> #include <memory> int main() { // 方法一:使用 make_shared 函数 (推荐) auto ptr1 = std::make_shared<int>(42); // 方法二:直接初始化 std::shared_ptr<int> ptr2(new int(10)); std::cout << *ptr1 << ", " << *ptr2 << std::endl; } ``` 上述代码展示了两种创建 `std::shared_ptr` 的方式。其中,`std::make_shared` 是更高效且安全的选择,因为它减少了两次内存分配操作[^1]。 --- #### 3. 拷贝与赋值 `std::shared_ptr` 支持拷贝和赋值操作,在这些过程中会更新引用计数。 ```cpp #include <iostream> #include <memory> int main() { std::shared_ptr<std::string> sptr1 = std::make_shared<std::string>("hello"); std::shared_ptr<std::string> sptr2; // 赋值操作 sptr2 = sptr1; std::cout << "sptr1 use count: " << sptr1.use_count() << "\n"; // 输出 2 std::cout << "sptr2 use count: " << sptr2.use_count() << "\n"; // 输出 2 return 0; } ``` 在此示例中,`use_count()` 方法返回当前对象的引用计数值。可以看到,经过赋值后,两个指针共享同一个对象的所有权。 --- #### 4. 自定义删除器 可以通过设置自定义删除器来改变默认的行为(即调用 `delete` 删除对象)。 ```cpp #include <iostream> #include <memory> void custom_deleter(int* p) { std::cout << "Custom deleter called\n"; delete p; } int main() { std::shared_ptr<int> sptr(new int(10), custom_deleter); // 当 sptr 超出范围时,custom_deleter 将被执行 } ``` 此代码片段演示了如何指定一个函数作为删除器,从而在对象销毁时执行特定逻辑。 --- #### 5. 应用场景分析 下面是一个基于 `std::shared_ptr` 构建 N 叉树节点的例子,类似于 Trie 结构的应用[^3]。 ```cpp #include <iostream> #include <vector> #include <memory> #include <unordered_map> using namespace std; // 定义 N 叉树节点 struct Node { char value; bool isEndOfWord; unordered_map<char, shared_ptr<Node>> children; Node(char c): value(c), isEndOfWord(false) {} }; class Trie { public: shared_ptr<Node> root; Trie(): root(make_shared<Node>(' ')) {} void insert(const string& word) { shared_ptr<Node> current = root; for (char c : word) { if (!current->children.count(c)) current->children[c] = make_shared<Node>(c); current = current->children[c]; } current->isEndOfWord = true; } bool search(const string& word) const { shared_ptr<Node> node = findNode(word); return node && node->isEndOfWord; } private: shared_ptr<Node> findNode(const string& prefix) const { shared_ptr<Node> current = root; for (char c : prefix) { if (!current->children.count(c)) return nullptr; current = current->children[c]; } return current; } }; ``` 在这个例子中,`std::shared_ptr` 确保了即使某些分支不再被访问,也不会发生内存泄漏。 --- #### 总结 `std::shared_ptr` 提供了一种方便的方式来进行动态内存管理,尤其适合多线程环境下的资源共享场景。然而需要注意的是,过度依赖可能会引发循环引用等问题,因此应谨慎设计数据结构。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值