C++智能指针
C++11标准引入了智能指针,旨在自动管理动态内存,避免内存泄漏和悬挂指针问题。C++标准库提供了三种主要的智能指针类型:std::unique_ptr、std::shared_ptr和std::weak_ptr。
- std::unique_ptr:适用于独占所有权的场景,不可复制但可移动,适用于单一对象的管理。
- std::shared_ptr:适用于共享所有权的场景,使用引用计数管理对象生命周期,可复制,适用于跨范围的对象管理。
- std::weak_ptr:不拥有对象,仅仅是一个观察者,适用于需要解决std::shared_ptr循环引用问题的场景
下面分别介绍它们的使用场景及示例代码
1. std::unique_ptr
std::unique_ptr 是一种独占所有权的智能指针,确保同一时刻只能有一个智能指针拥有对象的所有权。当std::unique_ptr对象销毁时,它所管理的对象也会被自动销毁。
适用场景:
- 独占所有权的场景。
- 对象生命周期在单一范围内(如单一函数或单一类)管理。
#include <iostream>
#include <memory>class MyClass {
public:MyClass() { std::cout << "MyClass Constructor\n"; }~MyClass() { std::cout << "MyClass Destructor\n"; }void sayHello() { std::cout << "Hello from MyClass\n"; }
};int main() {std::unique_ptr<MyClass> ptr1(new MyClass());ptr1->sayHello();// std::unique_ptr<MyClass> ptr2 = ptr1; // Error: can't copy unique_ptrstd::unique_ptr<MyClass> ptr2 = std::move(ptr1); // Transfer ownershipif (!ptr1) {std::cout << "ptr1 is now empty\n";}ptr2->sayHello();return 0;
}
2. std::shared_ptr
std::shared_ptr 是一种共享所有权的智能指针,多个智能指针可以共同拥有同一个对象。对象在最后一个所有者销毁时被自动销毁。std::shared_ptr内部使用引用计数来管理对象的生命周期。
适用场景:
- 需要共享所有权的场景。
- 对象需要跨多个范围或模块共享。
#include <iostream>
#include <memory>class MyClass {
public:MyClass() { std::cout << "MyClass Constructor\n"; }~MyClass() { std::cout << "MyClass Destructor\n"; }void sayHello() { std::cout << "Hello from MyClass\n"; }
};void useSharedPtr(std::shared_ptr<MyClass> ptr) {ptr->sayHello();std::cout << "useSharedPtr: Use count is " << ptr.use_count() << '\n';
}int main() {std::shared_ptr<MyClass> ptr1(new MyClass());std::cout << "main: Use count is " << ptr1.use_count() << '\n';useSharedPtr(ptr1);std::cout << "main: Use count is " << ptr1.use_count() << '\n';return 0;
}
3. std::weak_ptr
std::weak_ptr 是一种不拥有所有权的智能指针,它不影响所指对象的引用计数。std::weak_ptr必须从一个std::shared_ptr创建,用于解决循环引用问题。
适用场景:
- 需要观察但不拥有对象的场景。
- 解决循环引用问题。
#include <iostream>
#include <memory>class MyClass;class B;class MyClass {
public:std::shared_ptr<B> b_ptr;~MyClass() { std::cout << "MyClass Destructor\n"; }
};class B {
public:std::weak_ptr<MyClass> my_class_ptr;~B() { std::cout << "B Destructor\n"; }
};int main() {{auto a = std::make_shared<MyClass>();auto b = std::make_shared<B>();a->b_ptr = b;b->my_class_ptr = a; // No cycle, because weak_ptr doesn't affect reference count} // Both a and b are properly destroyed herestd::cout << "End of main\n";return 0;
}