C++智能指针完全指南
前言
智能指针是现代C++中管理动态内存的重要工具,它能够自动管理内存的生命周期,避免内存泄漏和悬空指针等问题。本文将详细介绍C++中的各种智能指针类型及其使用场景。
为什么需要智能指针?
在传统的C++编程中,我们使用new和delete来手动管理内存:
1 2 3
| int* ptr = new int(42);
delete ptr;
|
这种方式存在以下问题:
- 容易忘记释放内存
- 异常安全得不到保证
- 代码复杂且容易出错
智能指针类型
1. std::unique_ptr
unique_ptr是独占所有权的智能指针,同一时间只能有一个unique_ptr拥有对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| #include <memory> #include <iostream>
class MyClass { public: MyClass(int value) : value_(value) { std::cout << "MyClass constructed with value: " << value_ << std::endl; } ~MyClass() { std::cout << "MyClass destroyed with value: " << value_ << std::endl; } void show() { std::cout << "Value: " << value_ << std::endl; } private: int value_; };
int main() { std::unique_ptr<MyClass> ptr1 = std::make_unique<MyClass>(42); ptr1->show(); std::unique_ptr<MyClass> ptr2 = std::move(ptr1); if (ptr1 == nullptr) { std::cout << "ptr1 is now nullptr" << std::endl; } ptr2->show(); return 0; }
|
2. std::shared_ptr
shared_ptr允许多个智能指针共享同一个对象,使用引用计数来管理生命周期。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| #include <memory> #include <iostream>
class Resource { public: Resource(const std::string& name) : name_(name) { std::cout << "Resource '" << name_ << "' created" << std::endl; } ~Resource() { std::cout << "Resource '" << name_ << "' destroyed" << std::endl; } void use() { std::cout << "Using resource: " << name_ << std::endl; } private: std::string name_; };
int main() { std::shared_ptr<Resource> ptr1 = std::make_shared<Resource>("SharedResource"); std::cout << "Reference count: " << ptr1.use_count() << std::endl; { std::shared_ptr<Resource> ptr2 = ptr1; std::cout << "Reference count: " << ptr1.use_count() << std::endl; ptr1->use(); ptr2->use(); } std::cout << "Reference count: " << ptr1.use_count() << std::endl; ptr1->use(); return 0; }
|
3. std::weak_ptr
weak_ptr是对shared_ptr的弱引用,不会增加引用计数,用于解决循环引用问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| #include <memory> #include <iostream>
class Node { public: std::string name; std::shared_ptr<Node> next; std::weak_ptr<Node> parent; Node(const std::string& name) : name(name) { std::cout << "Node '" << name << "' created" << std::endl; } ~Node() { std::cout << "Node '" << name << "' destroyed" << std::endl; } void setParent(std::shared_ptr<Node> parent) { this->parent = parent; } void showParent() { if (auto parentPtr = parent.lock()) { std::cout << name << "'s parent is: " << parentPtr->name << std::endl; } else { std::cout << name << " has no parent or parent was destroyed" << std::endl; } } };
int main() { auto node1 = std::make_shared<Node>("Node1"); auto node2 = std::make_shared<Node>("Node2"); node1->next = node2; node2->setParent(node1); node1->showParent(); node2->showParent(); return 0; }
|
最佳实践
1. 优先使用make_unique和make_shared
1 2 3 4 5 6
| auto ptr = std::make_unique<MyClass>(42); auto sharedPtr = std::make_shared<MyClass>(42);
std::unique_ptr<MyClass> ptr(new MyClass(42));
|
2. 选择合适的智能指针类型
- 单一所有权:使用
unique_ptr
- 共享所有权:使用
shared_ptr
- 弱引用:使用
weak_ptr
3. 避免循环引用
1 2 3 4 5 6 7 8 9
| class A { public: std::shared_ptr<B> b; };
class B { public: std::weak_ptr<A> a; };
|
总结
智能指针是现代C++中管理内存的重要工具,正确使用智能指针可以:
- 自动管理内存生命周期
- 避免内存泄漏
- 提高代码安全性
- 简化内存管理代码
选择合适的智能指针类型,遵循最佳实践,可以写出更安全、更易维护的C++代码。