智能指针解释
智能指针(Smart Pointer)是C++中用于自动管理动态分配内存的工具。
它是一种封装了原始指针功能的类,能够自动处理资源的分配和释放,从而帮助程序员避免常见的内存管理错误,如内存泄漏、悬挂指针等问题。
智能指针通过资源获取即初始化(RAII, Resource Acquisition Is Initialization)的机制工作,这意味着智能指针在其构造时获取资源,在其析构时释放资源。这样可以确保即使在异常情况下,资源也能被正确地释放。
智能指针解决的问题
(1)内存泄漏:内存手动释放,使用智能指针可以自动释放。
(2)共享所有权指针的传播和释放,比如多线程使用同一个对象时析构问题。
几种类型的智能指针
C++标准库提供了几种类型的智能指针,包括:
-
std::unique_ptr
:- 独占所有权模型,意味着一个
unique_ptr
实例拥有它所指向的对象的独占所有权。 - 当
unique_ptr
超出作用域或被显式重置时,它会自动调用析构函数并释放所管理的对象。 - 不支持复制,但可以移动。
- 独占所有权模型,意味着一个
-
std::shared_ptr
:- 共享所有权模型,允许多个
shared_ptr
实例共享同一个对象的所有权。 - 使用引用计数来跟踪指向同一对象的
shared_ptr
的数量。 - 当最后一个
shared_ptr
实例超出作用域或被重置时,引用计数减至零,对象的析构函数被调用,对象被释放。
- 共享所有权模型,允许多个
-
std::weak_ptr
:- 用于解决
shared_ptr
的循环引用问题。 - 不增加引用计数,可以观察由
shared_ptr
管理的对象,但不参与其生命周期管理。 - 当没有
shared_ptr
实例指向对象时,weak_ptr
可以检测到对象已被销毁。
- 用于解决
智能指针的设计和使用极大地简化了C++中的内存管理,提高了程序的健壮性和安全性。在现代C++编程中,强烈推荐使用智能指针代替裸指针,以提高代码的质量和可维护性。
智能指针举例
智能指针在C++中是用来自动管理动态分配的内存的一种手段,以防止内存泄漏和其他资源管理相关的问题。
std::unique_ptr
示例
std::unique_ptr
是一种独占所有权的智能指针,它确保任何时候只有一个std::unique_ptr
实例拥有对给定资源的控制。当std::unique_ptr
超出作用域或被重置时,它所拥有的资源会被自动释放。
#include <memory>
class MyClass {
public:
MyClass() { std::cout << "MyClass constructor called.\n"; }
~MyClass() { std::cout << "MyClass destructor called.\n"; }
void doSomething() { std::cout << "Doing something...\n"; }
};
int main() {
// 创建一个unique_ptr来管理MyClass的实例
std::unique_ptr<MyClass> uptr(new MyClass());
// 调用doSomething方法
uptr->doSomething();
// unique_ptr会在离开作用域时自动调用MyClass的析构函数
return 0;
}
std::shared_ptr
示例
std::shared_ptr
是一种共享所有权的智能指针,它允许多个std::shared_ptr
实例共享同一资源的所有权。std::shared_ptr
使用引用计数来跟踪有多少个智能指针指向相同的资源,当引用计数变为0时,资源会被释放。
#include <memory>
class MyClass {
public:
MyClass() { std::cout << "MyClass constructor called.\n"; }
~MyClass() { std::cout << "MyClass destructor called.\n"; }
void doSomething() { std::cout << "Doing something...\n"; }
};
int main() {
// 创建一个shared_ptr来管理MyClass的实例
std::shared_ptr<MyClass> sptr(new MyClass());
// 创建第二个shared_ptr,共享同一个MyClass实例
std::shared_ptr<MyClass> sptr2 = sptr;
// 调用doSomething方法
sptr->doSomething();
// 当所有shared_ptr实例都超出作用域时,MyClass的析构函数才会被调用
return 0;
}
注意事项
在使用std::shared_ptr
时,要小心避免循环引用的情况,这会导致引用计数永远不降为0,从而导致资源泄露。在有循环引用的情况下,可以使用std::weak_ptr
来打破循环,std::weak_ptr
不增加引用计数,只持有对std::shared_ptr
管理资源的弱引用。
这些示例展示了如何使用智能指针来管理动态分配的内存,以确保在适当的时候资源能够被正确释放,避免了手动管理内存时可能出现的常见错误。
其他示例
https://www.cnblogs.com/god-of-death/p/17962676
https://zhuanlan.zhihu.com/p/678722914