C++ 智能指针教程
C++ 中的智能指针提供了自动且安全的内存管理。它们通过 RAII(资源获取即初始化)机制,帮助开发者避免内存泄漏和悬空指针的问题,确保对象在生命周期结束时被正确释放。
本教程将介绍 C++ 中三种主要的智能指针:
std::unique_ptr:独占式所有权std::shared_ptr:共享式所有权std::weak_ptr:非拥有式弱引用
1. std::unique_ptr
unique_ptr 拥有独占所有权。一个资源只能被一个 unique_ptr 拥有。
示例:管理简单对象
#include <iostream>
#include <memory>
int main() {
std::unique_ptr<int> p = std::make_unique<int>(42);
std::cout << "值: " << *p << "\n";
// 转移所有权
std::unique_ptr<int> q = std::move(p);
if (!p) std::cout << "p 现在是空指针\n";
std::cout << "q 指向: " << *q << "\n";
}
示例:构建链表
struct Node {
int val;
std::unique_ptr<Node> next;
Node(int v) : val(v), next(nullptr) {}
};
void printList(const std::unique_ptr<Node>& head) {
const Node* curr = head.get();
while (curr) {
std::cout << curr->val << " ";
curr = curr->next.get();
}
std::cout << "\n";
}
int main() {
auto head = std::make_unique<Node>(1);
head->next = std::make_unique<Node>(2);
head->next->next = std::make_unique<Node>(3);
printList(head);
}
2. std::shared_ptr
shared_ptr 允许多个指针共享同一个资源的所有权。它通过引用计数管理资源,当引用数为零时自动释放内存。
示例:共享资源
#include <iostream>
#include <memory>
int main() {
std::shared_ptr<int> a = std::make_shared<int>(100);
std::shared_ptr<int> b = a;
std::cout << "a 的引用计数: " << a.use_count() << "\n";
std::cout << "b 的引用计数: " << b.use_count() << "\n";
std::cout << "*b = " << *b << "\n";
}
示例:共享链表节点
struct Node {
int val;
std::shared_ptr<Node> next;
Node(int v) : val(v), next(nullptr) {}
};
3. std::weak_ptr
weak_ptr 是一种弱引用,不拥有资源,仅用于观察 shared_ptr 所管理的对象。它常用于打破循环引用,防止内存泄漏。
示例:打破循环引用
#include <iostream>
#include <memory>
struct B;
struct A {
std::shared_ptr<B> b_ptr;
~A() { std::cout << "A 被销毁\n"; }
};
struct B {
std::weak_ptr<A> a_ptr;
~B() { std::cout << "B 被销毁\n"; }
};
int main() {
auto a = std::make_shared<A>();
auto b = std::make_shared<B>();
a->b_ptr = b;
b->a_ptr = a;
}
是否存在 make_weak?
不存在 std::make_weak,因为 weak_ptr 不拥有资源,它必须引用一个已存在的 shared_ptr。
如何创建 weak_ptr
#include <iostream>
#include <memory>
int main() {
std::shared_ptr<int> sp = std::make_shared<int>(42);
std::weak_ptr<int> wp = sp;
if (auto locked = wp.lock()) {
std::cout << "值: " << *locked << "\n";
} else {
std::cout << "对象已被释放\n";
}
}
总结
| 智能指针 | 所有权 | 线程安全的引用计数 | 典型用途 |
|---|---|---|---|
unique_ptr |
独占 | N/A | 高效、安全的单一所有权 |
shared_ptr |
共享 | 是 | 多个所有者共享资源 |
weak_ptr |
无 | N/A | 打破 shared_ptr 的循环引用 |
C/C++编程
- 理解C++中的std::transform_reduce及示例
- 使用原子 TAS 指令实现自旋锁
- C++中检测编译时与运行时: if consteval 与 std::is_constant_evaluated()
- C++ 转发引用: 完美转发的关键
- 理解 C++ 中的 dynamic_cast: 安全的向下转型与向上转型
- C与C++: restrict关键字及其在编译器优化中的作用
- C++的左值/lvalue, 右值/rvalue和右值引用/rvalue references
- C++中的assert和static_assert的区别
- C++: auto_ptr智能指针被弃用
- C++中的consteval是什么? 它与const和constexpr有何不同?
- C++ 教程: 用std::move来移动所有权
- C++中的 const和constexpr 比较
- 简易教程: C++的智能指针
- C++ 编程练习题: 如何合并两个二叉树?
- C++ 编程练习题 - 找出第三大的数
- C++ 编程练习题 - 最多连续的 1
- C++ 编程练习题 - 左子树叶节点之和 (深度优先+广度优先+递归)
- C++ 编程练习题 - 最多水容器 (递归)
- C++的异步编程: std::future, std::async 和 std::promise
- C编程练习题: 翻转整数位
- C++编程练习题: 找出字符串的所有大小小组合
- C/C++ 中的内存管理器(堆与栈)
- C++编程练习题: 对两单向链表求和
英文:Tutorial on C++ Smart Pointers
本文一共 375 个汉字, 你数一下对不对.上一篇: 借助AI快速开源了N个小工具: 写代码越来越像做产品了, AI 真把我宠坏了(Vibe Coding)
下一篇: C++ Ranges 教程
扫描二维码,分享本文到微信朋友圈