【C++】什么是智能指针及应用
在 C++ 项目中,智能指针是管理动态内存的重要工具,能有效避免内存泄漏。Android Framework 中大量使用了自定义的智能指针(sp/wp),标准库的std::shared_ptr和std::unique_ptr也在很多场景中应用。
判断什么时候用智能指针很简单,核心就看谁来负责释放内存。手动管理内存容易出错(比如忘记释放、重复释放),智能指针的作用就是自动帮你释放内存,避免这些问题。
用一个生活例子类比:
- 手动管理内存 = 你自己租房,到期必须记得退租,否则会罚款(内存泄漏);退错房(重复释放)也会出问题。
- 智能指针 = 找了个管家,到期自动退租,你不用操心。
一、必须用智能指针的 3 种场景
1. 动态分配的内存(用new创建的对象)
只要你用了new,就必须考虑释放。这时用智能指针最安全。
// 错误示例:手动管理容易忘释放
void func() {int* p = new int(10); // 分配内存// ... 中间代码如果 return 或抛异常,下面的 delete 不会执行,导致内存泄漏delete p; // 手动释放,风险高
}// 正确示例:用智能指针自动释放
void func() {std::unique_ptr<int> p(new int(10)); // 分配后交给智能指针// ... 无论中间发生什么,出了作用域自动释放
}
2. 内存需要在多个地方共享
比如一个对象需要被多个函数或类同时使用,用std::shared_ptr可以自动跟踪 “谁还在用”,最后一个使用者用完才释放。
// 场景:一张图片被多个UI组件显示
class Image {
public:Image(const std::string& path) { /* 加载图片 */ }
};void showInWindowA(std::shared_ptr<Image> img) { /* 显示图片 */ }
void showInWindowB(std::shared_ptr<Image> img) { /* 显示图片 */ }int main() {auto img = std::make_shared<Image>("photo.jpg"); // 共享指针showInWindowA(img); // 传递共享指针(引用计数+1)showInWindowB(img); // 传递共享指针(引用计数+1)// 当所有地方都不用img了,自动释放图片内存
}
3. 函数需要返回动态分配的对象
如果函数返回new出来的对象,用智能指针可以避免调用者忘记释放。
// 错误示例:返回裸指针,调用者可能忘释放
Image* createImage() {return new Image("pic.jpg"); // 谁来delete?不知道
}// 正确示例:返回智能指针,自动管理
std::unique_ptr<Image> createImage() {return std::make_unique<Image>("pic.jpg"); // 调用者不用管释放
}
二、不需要用智能指针的 3 种场景
1. 栈上的对象(不用new创建的)
栈上的对象会自动销毁,不需要智能指针。
void func() {int a = 10; // 栈上变量,出作用域自动消失Image img("pic.jpg"); // 栈上对象,出作用域自动调用析构函数// 不需要任何指针管理
}
2. 全局 / 静态变量
全局变量在程序结束时自动释放,静态变量在作用域结束时自动释放。
Image g_globalImg("global.jpg"); // 全局对象,程序结束时自动销毁void func() {static Image s_staticImg("static.jpg"); // 静态对象,函数第一次调用时创建,程序结束时销毁
}
3. 已经由其他系统管理的内存
比如 Android Framework 中,有些对象由系统服务(如Binder)管理生命周期,这时不需要用智能指针。
// 示例:Android中获取系统服务(服务生命周期由系统管理)
sp<IServiceManager> sm = defaultServiceManager(); // 系统提供的智能指针
sp<IBinder> binder = sm->getService(String16("media.player")); // 系统管理的对象
// 这里的sp是Android自定义智能指针,但原理和std::shared_ptr一样
总结:一句话判断
只要你写了new,就必须用智能指针(或者有明确的手动释放逻辑,但不推荐)。
其他情况(栈对象、全局对象、系统管理的对象)不需要用。
智能指针的核心价值就是:代替人来记着释放内存,减少 “忘记释放” 或 “重复释放” 的低级错误,尤其在复杂项目中能大幅提升代码安全性。