侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1823 篇文章
  • 累计收到 0 条评论

智能指针与资源管理

2025-12-12 / 0 评论 / 4 阅读

题目

智能指针与资源管理

信息

  • 类型:问答
  • 难度:⭐⭐

考点

智能指针的使用,移动语义,自定义删除器

快速回答

在C++11及以上版本中,智能指针是管理动态内存的核心工具:

  • 优先使用std::unique_ptr实现独占所有权资源管理
  • 需要共享所有权时使用std::shared_ptr并注意循环引用问题
  • 通过移动语义(std::move)转移unique_ptr所有权
  • 对非内存资源(如文件句柄)使用自定义删除器
## 解析

问题场景

假设需要实现一个FileHandler类,封装文件操作并满足:

  1. 文件资源在对象销毁时自动关闭
  2. 支持所有权的安全转移
  3. 避免资源泄漏和重复释放

原理说明

C++11引入的智能指针通过RAII(资源获取即初始化)机制自动管理资源:

  • std::unique_ptr:独占所有权,不可复制但可移动
  • std::shared_ptr:共享所有权,基于引用计数
  • 自定义删除器:允许指定资源释放逻辑(如fclose

代码实现

#include <memory>
#include <cstdio>

class FileHandler {
public:
    // 自定义删除器
    struct FileDeleter {
        void operator()(FILE* fp) const {
            if(fp) {
                std::fclose(fp);
                std::cout << "File closed\n";
            }
        }
    };

    // 使用 unique_ptr 管理文件资源
    using UniqueFilePtr = std::unique_ptr<FILE, FileDeleter>;

    explicit FileHandler(const char* filename, const char* mode)
        : file_(std::fopen(filename, mode)) {
        if(!file_) throw std::runtime_error("File open failed");
    }

    // 支持移动语义
    FileHandler(FileHandler&&) = default;
    FileHandler& operator=(FileHandler&&) = default;

    void write(const char* data) {
        if(std::fputs(data, file_.get()) == EOF)
            throw std::runtime_error("Write error");
    }

private:
    UniqueFilePtr file_;
};

// 使用示例
int main() {
    FileHandler f1("test.txt", "w");
    f1.write("Hello ");

    // 所有权转移
    FileHandler f2 = std::move(f1);
    f2.write("World!");

    return 0;
} // 文件自动关闭

最佳实践

  1. 首选unique_ptr:默认使用独占所有权,避免引用计数开销
  2. 移动而非复制:通过std::move转移资源所有权
  3. 自定义删除器:管理非内存资源(文件/网络套接字等)
  4. 避免裸指针:不调用get()获取底层指针除非必要

常见错误

错误示例后果修正方案
std::unique_ptr<FILE> ptr(fopen(...));未调用fclose导致资源泄漏添加自定义删除器
FileHandler f3 = f2;编译错误(复制被禁用)使用std::move
fclose(file_.get());导致重复释放依赖RAII自动管理

扩展知识

  • std::shared_ptr:当需要共享所有权时使用,注意用std::make_shared创建
  • std::weak_ptr:解决shared_ptr循环引用问题
  • enable_shared_from_this:在类内部获取自身的shared_ptr
  • C++17新增的std::unique_ptr<T[]>支持数组类型