qq_40698103头像

c++智能指针四 自定义删除器了解一下

这又是什么新奇玩意呀?

自定义删除器是智能指针(std::unique_ptr / std::shared_ptr)的一个特性:允许你指定一个函数或函数对象,在智能指针析构时用它来释放资源,而不是默认的 delete。

为什么需要它

默认情况下 unique_ptr<T> 用 delete ptr 释放,unique_ptr<T[]> 用 delete[] ptr。但很多资源的释放方式不是 delete:

  • C 风格 API 分配的内存:malloc需要 free

  • 文件句柄:fopen需要 fclose

  • 系统句柄:CreateFile / socket / HANDLE需要对应的 CloseHandle / close

  • 第三方库对象:需要调用专门的 xxx_destroy() 函数

如果你的智能指针管的是你自己写的 class/struct,且它的析构函数已经正确清理了它内部持有的资源 ,那么不需要自定义删除器。

 ps:还记的析构函数需要处理哪些资源吗?如果不记得,可以看看这篇文章:c++析构函数应该处理哪些资源

如果你的智能指针管的是"一个裸句柄/裸指针"(比如 FILE*、HANDLE、void*),那这个"被管理的类型"根本没有析构函数 ,就需要自定义删除器。

这种情况在实际开发也许会遇到

下面就以简单的示例代码来说明自定义删除器吧

情况一:不需要自定义删除器

#include <cstdio>
#include <memory>

class FileWrapper {
public:
    explicit FileWrapper(const char* path) : fp_(std::fopen(path, "w")) {}
    FileWrapper(const FileWrapper&) = delete;
    FileWrapper& operator=(const FileWrapper&) = delete;
    ~FileWrapper() {
        if (fp_) std::fclose(fp_);   // 析构函数负责关闭
    }
    std::FILE* get() const { return fp_; }
private:
    std::FILE* fp_;
};

int main() {
    // 管的是 FileWrapper 对象本身
    auto p = std::make_unique<FileWrapper>("a.txt");
    // p 析构 -> 调用 ~FileWrapper() -> fclose(fp_)
    // 默认删除器 default_delete<FileWrapper> 做的是 delete p.get(),
    // 而 delete 会调用 ~FileWrapper(),资源被正确释放
}

情况二:需要自定义删除器

#include <cstdio>
#include <memory>
#include <stdexcept>
#include <windows.h>

class FileHandle {
public:
    // 构造:接管一个已打开的 FILE*
    explicit FileHandle(std::FILE* f) : fp_(f, &std::fclose) {}

    // 取裸句柄,用于调用 C 风格 API(如 fputs / fread)
    std::FILE* get() const { return fp_.get(); }

    // 是否持有有效句柄
    explicit operator bool() const { return fp_ != nullptr; }

    // 显式关闭(可选):提前释放资源
    void reset() { fp_.reset(); }

    // 禁止拷贝(unique_ptr 本身已禁拷贝,这里显式写出更清晰)
    FileHandle(const FileHandle&) = delete;
    FileHandle& operator=(const FileHandle&) = delete;

    // 允许移动(unique_ptr 支持移动,编译器会隐式生成)
    FileHandle(FileHandle&&) noexcept = default;
    FileHandle& operator=(FileHandle&&) noexcept = default;

private:
    // 核心:unique_ptr 持有 FILE*,删除器是 fclose
    std::unique_ptr<std::FILE, decltype(&std::fclose)> fp_;
};

int main() {

    // 设置控制台输出编码为 UTF-8
    SetConsoleOutputCP(65001); 

    // 1) 打开文件并交给 FileHandle 管理
    std::FILE* raw = std::fopen("demo.txt", "w");
    if (!raw) {
        std::perror("fopen");
        return 1;
    }
    FileHandle fh(raw);

    if (!fh) {
        std::fprintf(stderr, "文件句柄无效\n");
        return 1;
    }

    // 2) 使用:通过 get() 拿裸指针调用 C API
    std::fputs("hello, FileHandle\n", fh.get());
    std::fputs("second line\n", fh.get());

    std::printf("写入完成,句柄地址 = %p\n", static_cast<void*>(fh.get()));

    // 3) 离开作用域时,fh 析构 -> fp_ 析构 -> 自动调用 fclose
    //    无需手动 fclose
    std::printf("--- 即将离开作用域,自动 fclose ---\n");
    return 0;
}

运行结果

入完成,句柄地址 = 000001b8ec3f45c0
--- 即将离开作用域,自动 fclose ---

写入的demo.txt文件内容如下

hello, FileHandle
second line

上一篇:C++智能指针三 weak_ptr:弱引用

下一篇:c++析构函数应该处理哪些资源

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/qq_40698103/article/details/170608744

文章来源转载

评论

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--