C++ 中的智能指针(Smart Pointer)是用于管理动态内存分配的工具,它们能够自动管理资源的生命周期,避免内存泄漏。智能指针是 C++11 标准引入的,通过模板类封装原生指针,实现资源的自动释放。主要的智能指针包括 std::shared_ptr
和 std::unique_ptr
。
1. std::unique_ptr
std::unique_ptr
是一种独占所有权的智能指针,表示某个资源只能被一个指针管理。它确保同一资源在程序中只会有一个指针指向,当 std::unique_ptr
被销毁时,资源会被自动释放。
特点
-
独占所有权:
std::unique_ptr
禁止拷贝操作,确保唯一所有权。 -
自动释放资源:当
std::unique_ptr
超出作用域时,资源自动释放。 -
移动语义:可以通过
std::move
转移所有权,但不能复制。
常用操作
-
创建和使用:使用
std::make_unique
创建std::unique_ptr
。 -
访问资源:通过
operator*
和operator->
访问资源。 -
释放资源:可以使用
reset
手动释放资源。
示例代码
#include <iostream>
#include <memory> // 包含 unique_ptr 所在的头文件
int main() {
// 创建 unique_ptr 并指向一个动态分配的 int
std::unique_ptr<int> ptr = std::make_unique<int>(10);
// 访问指针的值
std::cout << "Value: " << *ptr << std::endl;
// 不能复制 unique_ptr
// std::unique_ptr<int> ptr2 = ptr; // 错误
// 可以通过移动语义转移所有权
std::unique_ptr<int> ptr2 = std::move(ptr);
if (!ptr) {
std::cout << "ptr is now nullptr after moving ownership." << std::endl;
}
return 0;
}
输出
Value: 10
ptr is now nullptr after moving ownership.
2. std::shared_ptr
std::shared_ptr
是一种共享所有权的智能指针,允许多个指针共享同一个资源。std::shared_ptr
内部维护一个引用计数,记录有多少个 shared_ptr
指向该资源。当最后一个 shared_ptr
被销毁时,资源会自动释放。
特点
-
共享所有权:多个
shared_ptr
可以指向同一个资源。 -
引用计数:每个
shared_ptr
维护资源的引用计数。 - 自动释放资源:当引用计数为 0 时,资源自动释放。
常用操作
-
创建和使用:使用
std::make_shared
创建std::shared_ptr
。 -
访问资源:通过
operator*
和operator->
访问资源。 -
引用计数:通过
use_count
查看当前的引用计数。
示例代码
#include <iostream>
#include <memory> // 包含 shared_ptr 所在的头文件
int main() {
// 创建 shared_ptr 并指向一个动态分配的 int
std::shared_ptr<int> ptr1 = std::make_shared<int>(20);
// 打印引用计数
std::cout << "Reference count: " << ptr1.use_count() << std::endl;
{
// 创建一个新的 shared_ptr,指向相同资源
std::shared_ptr<int> ptr2 = ptr1;
std::cout << "Reference count after creating ptr2: " << ptr1.use_count() << std::endl;
}
// ptr2 超出作用域,引用计数减少
std::cout << "Reference count after ptr2 goes out of scope: " << ptr1.use_count() << std::endl;
return 0;
}
输出:
Reference count: 1
Reference count after creating ptr2: 2
Reference count after ptr2 goes out of scope: 1
3. std::weak_ptr
std::weak_ptr
是一种非拥有型的智能指针,用于解决 shared_ptr
的循环引用问题。它不会增加资源的引用计数,仅持有资源的一个弱引用,无法直接访问资源,需通过 lock
方法获得一个 shared_ptr
来使用。
示例代码
#include <iostream>
#include <memory>
int main() {
std::shared_ptr<int> sp = std::make_shared<int>(30);
std::weak_ptr<int> wp = sp; // 使用 weak_ptr 指向同一资源
std::cout << "Reference count: " << sp.use_count() << std::endl;
if (auto spt = wp.lock()) { // 通过 lock 创建一个 shared_ptr
std::cout << "Weak pointer is valid, value: " << *spt << std::endl;
} else {
std::cout << "Weak pointer is expired." << std::endl;
}
sp.reset(); // 释放 shared_ptr 所有权
if (wp.expired()) {
std::cout << "Weak pointer is now expired." << std::endl;
}
return 0;
}
输出:
Reference count: 1
Weak pointer is valid, value: 30
Weak pointer is now expired.
总结
智能指针 | 特点 | 使用场景 |
---|---|---|
std::unique_ptr |
独占所有权,不允许复制;可以通过 std::move 转移所有权 |
需要独占管理资源,避免拷贝操作 |
std::shared_ptr |
共享所有权,使用引用计数管理资源的生命周期 | 多个对象共享资源,需自动释放资源 |
std::weak_ptr |
非拥有型指针,不影响引用计数,用于解决循环引用问题 | 检查或跟踪资源是否仍然存在 |
std::unique_ptr
和 std::shared_ptr
提供了简单、灵活的资源管理方式,有效降低内存泄漏风险。而 std::weak_ptr
主要用于防止 shared_ptr
的循环引用。