文章目录
前言
在 C++ 编程中,智能指针是一种重要的工具,用于自动管理动态分配的内存。std::shared_ptr
是 C++11 引入的智能指针之一,它允许多个 std::shared_ptr
实例共享对同一个对象的所有权。std::shared_ptr
通过引用计数机制来管理内存的生命周期,确保对象在最后一个 std::shared_ptr
被销毁时才释放。
为什么使用 std::shared_ptr
- 共享所有权:
std::shared_ptr
允许多个指针共享对同一个对象的所有权,适用于需要多个实体引用同一对象的场景。 - 自动内存管理:智能指针自动管理对象的生命周期,避免了内存泄漏的问题。
- 引用计数:内置的引用计数机制确保对象在所有
std::shared_ptr
实例都不再使用时才被释放。
std::shared_ptr
与 std::unique_ptr
的区别
-
所有权管理:
std::unique_ptr
:独占所有权,确保同一时间只有一个智能指针拥有对象的所有权,不能被复制,只能移动。std::shared_ptr
:允许多个智能指针共享同一个对象的所有权,通过引用计数机制来管理对象的生命周期。
-
引用计数:
std::unique_ptr
:没有引用计数,简单高效。std::shared_ptr
:使用引用计数来管理对象的生命周期,较为复杂但支持共享所有权。
std::shared_ptr
的构造函数和操作函数
构造函数
-
默认构造函数
std::shared_ptr();
std::shared_ptr<int> p; // 创建一个空的 shared_ptr
-
构造函数(原始指针)
explicit std::shared_ptr(T* ptr);
std::shared_ptr<int> p(new int(10)); // 使用原始指针构造 shared_ptr
-
拷贝构造函数
std::shared_ptr(const std::shared_ptr& other);
std::shared_ptr<int> p1(new int(20)); std::shared_ptr<int> p2(p1); // 拷贝构造
-
移动构造函数
std::shared_ptr(std::shared_ptr&& other) noexcept;
std::shared_ptr<int> p1(new int(30)); std::shared_ptr<int> p2(std::move(p1)); // 移动构造
成员函数
-
reset
void reset(T* ptr = nullptr);
std::shared_ptr<int> p(new int(40)); p.reset(new int(50)); // 释放旧对象并拥有新对象
-
get
T* get() const noexcept;
std::shared_ptr<int> p(new int(60)); int* rawPtr = p.get(); // 获取原始指针
-
use_count
long use_count() const noexcept;
std::shared_ptr<int> p1(new int(70)); std::shared_ptr<int> p2 = p1; std::cout << "Use count: " << p1.use_count() << std::endl; // 输出引用计数
-
operator*
T& operator*() const;
std::shared_ptr<int> p(new int(80)); std::cout << *p << std::endl; // 访问管理的对象
-
operator->
T* operator->() const;
struct MyClass { void display() const { std::cout << "Hello" << std::endl; } }; std::shared_ptr<MyClass> p(new MyClass()); p->display(); // 访问对象的成员函数
如果有多个 std::shared_ptr
指向同一内存
std::shared_ptr
允许多个智能指针实例共享对同一个对象的所有权。引用计数会随着 std::shared_ptr
实例的创建和销毁而增加或减少。当最后一个 std::shared_ptr
实例被销毁时,管理的对象才会被释放。
std::shared_ptr<int> p1(new int(90));
std::shared_ptr<int> p2 = p1; // 共享所有权
std::cout << "Use count: " << p1.use_count() << std::endl; // 输出引用计数
p1.reset(); // 释放 p1 的所有权
std::cout << "Use count after reset p1: " << p2.use_count() << std::endl; // 输出引用计数
p2.reset(); // 释放 p2 的所有权,对象将被销毁
示例代码
下面的示例展示了 std::shared_ptr
的各种构造函数和操作函数的用法:
#include <iostream>
#include <memory>
struct MyClass {
MyClass(int v) : value(v) {}
int value;
void display() const { std::cout << "Value: " << value << std::endl; }
};
int main() {
// 使用默认构造函数
std::shared_ptr<int> p1;
// 使用原始指针构造函数
std::shared_ptr<int> p2(new int(10));
std::cout << "p2: " << *p2 << std::endl;
// 使用拷贝构造函数
std::shared_ptr<int> p3(p2);
std::cout << "p3: " << *p3 << std::endl;
// 使用移动构造函数
std::shared_ptr<int> p4(std::move(p2));
if (!p2) {
std::cout << "p2 is now empty" << std::endl;
}
// 使用 reset 函数
p4.reset(new int(20));
std::cout << "p4: " << *p4 << std::endl;
// 使用 get 函数
std::shared_ptr<MyClass> p5(new MyClass(30));
MyClass* rawPtrClass = p5.get();
rawPtrClass->display();
// 使用 use_count 函数
std::cout << "Use count of p5: " << p5.use_count() << std::endl;
// 使用 operator* 和 operator->
std::shared_ptr<MyClass> p6(new MyClass(40));
std::cout << "p6 value: " << p6->value << std::endl;
(*p6).display();
// 演示多个 shared_ptr
std::shared_ptr<int> p7(new int(50));
std::shared_ptr<int> p8 = p7; // 共享所有权
std::cout << "Use count: " << p7.use_count() << std::endl;
p7.reset(); // 释放 p7 的所有权
std::cout << "Use count after reset p7: " << p8.use_count() << std::endl;
p8.reset(); // 释放 p8 的所有权,对象将被销毁
return 0;
}
总结
std::shared_ptr
是一个强大的智能指针,用于管理动态分配的内存,并允许多个指针共享同一对象的所有权。通过引用计数机制,std::shared_ptr
确保对象在最后一个指针被销毁时才释放,避免了内存泄漏和悬空指针的问题。了解 std::shared_ptr
的构造函数和操作函数,有助于在需要共享对象所有权的场景中更安全、有效地管理内存。