0

0

怎样自定义C++智能指针的删除器 演示函数对象和lambda表达式的用法

P粉602998670

P粉602998670

发布时间:2025-08-02 12:00:04

|

813人浏览过

|

来源于php中文网

原创

自定义c++智能指针的删除器,是通过赋予智能指针在对象生命周期结束时释放资源的权力,以适应复杂资源管理需求。1. 对于std::unique_ptr,删除器类型是其类型定义的一部分,在编译时确定,提供更强类型安全性和运行时性能优化;2. 对于std::shared_ptr,删除器在构造时指定,所有共享同一资源的实例共用该删除器,提供运行时灵活性;3. 删除器可通过函数对象或lambda表达式实现,如关闭文件、释放非new分配内存、系统资源等;4. 处理删除器异常时,应在删除器内部捕获并处理异常,避免程序意外终止;5. unique_ptr适用于唯一所有权场景,shared_ptr适用于资源共享场景。

怎样自定义C++智能指针的删除器 演示函数对象和lambda表达式的用法

自定义 C++ 智能指针的删除器,本质上就是赋予智能指针在对象生命周期结束时,如何释放其所管理资源的权力。这允许我们超越默认的

delete
操作,以适应各种复杂的资源管理需求。

怎样自定义C++智能指针的删除器 演示函数对象和lambda表达式的用法

解决方案

怎样自定义C++智能指针的删除器 演示函数对象和lambda表达式的用法

C++ 智能指针(

std::unique_ptr
std::shared_ptr
)提供了自定义删除器的机制。关键在于模板参数。

立即学习C++免费学习笔记(深入)”;

  • std::unique_ptr
    :
    删除器类型是
    unique_ptr
    类型定义的一部分。这意味着
    unique_ptr
    的类型会因为删除器的不同而不同。这使得编译器可以进行更强的类型检查,并且通常可以避免运行时的性能损失。
  • std::shared_ptr
    :
    删除器在构造
    shared_ptr
    时指定。所有使用相同原始指针的
    shared_ptr
    实例共享相同的删除器。

函数对象 (Functor)

怎样自定义C++智能指针的删除器 演示函数对象和lambda表达式的用法

函数对象是一个类,它重载了函数调用操作符

operator()
。 我们可以创建一个函数对象,在其
operator()
中定义我们的资源释放逻辑。

#include 
#include 

// 自定义删除器:文件关闭
struct FileCloser {
    void operator()(FILE* file) const {
        if (file) {
            fclose(file);
            std::cout << "File closed.\n";
        }
    }
};

int main() {
    // 使用函数对象作为删除器
    std::unique_ptr file(fopen("example.txt", "w"), FileCloser());

    if (file) {
        fprintf(file.get(), "Hello, world!\n");
    } // 文件将在 file 离开作用域时自动关闭

    return 0;
}

在这个例子中,

FileCloser
是一个函数对象,它接受一个
FILE*
指针并在其
operator()
中关闭文件。
std::unique_ptr
被声明为
std::unique_ptr
,这意味着它将使用
FileCloser
来删除它所管理的
FILE*
指针。

Lambda 表达式

Lambda 表达式提供了一种更简洁的方式来定义删除器,特别是对于简单的资源释放逻辑。

#include 
#include 

int main() {
    // 使用 Lambda 表达式作为删除器
    std::unique_ptr file(fopen("example.txt", "w"), [](FILE* f){
        if (f) {
            fclose(f);
            std::cout << "File closed by lambda.\n";
        }
    });

    if (file) {
        fprintf(file.get(), "Hello from lambda!\n");
    }

    return 0;
}

这里,我们直接在

unique_ptr
的构造函数中提供了一个 lambda 表达式作为删除器。注意
unique_ptr
的类型定义现在是
std::unique_ptr
。 这是因为 lambda 表达式会被转换为一个函数指针,所以我们需要显式地指定函数指针的类型。 如果lambda没有捕获任何变量,它可以隐式转换为函数指针。

std::shared_ptr
中的删除器

怪兽AI数字人
怪兽AI数字人

数字人短视频创作,数字人直播,实时驱动数字人

下载

shared_ptr
的删除器是在构造函数中指定的,并且所有指向同一资源的
shared_ptr
实例共享相同的删除器。

#include 
#include 

int main() {
    FILE* file = fopen("example.txt", "w");
    if (!file) {
        std::cerr << "Failed to open file.\n";
        return 1;
    }

    // 使用 shared_ptr 和 Lambda 表达式
    std::shared_ptr sharedFile(file, [](FILE* f){
        if (f) {
            fclose(f);
            std::cout << "File closed by shared_ptr.\n";
        }
    });

    fprintf(sharedFile.get(), "Hello from shared_ptr!\n");

    // 当 sharedFile 离开作用域时,文件将被关闭
    return 0;
}

在这个例子中,我们创建了一个

shared_ptr
,它管理一个
FILE*
指针,并使用一个 lambda 表达式作为删除器。当最后一个指向该文件的
shared_ptr
实例离开作用域时,lambda 表达式将被调用,文件将被关闭。

何时应该自定义智能指针删除器?

当需要执行的资源释放操作不仅仅是简单的

delete
时,就需要自定义删除器。 典型场景包括:

  • 释放非
    new
    分配的内存:
    例如,使用
    malloc
    分配的内存需要使用
    free
    释放。
  • 释放文件句柄、网络连接等系统资源: 这些资源需要使用特定的系统调用来释放,例如
    fclose
    closesocket
    等。
  • 释放 COM 对象: COM 对象需要使用
    Release
    方法来释放。
  • 执行一些额外的清理操作: 例如,在对象销毁时记录日志。

自定义删除器可以确保资源得到正确释放,避免内存泄漏和其他资源泄漏问题。

unique_ptr
shared_ptr
在删除器使用上的区别是什么?

unique_ptr
的删除器类型是其类型定义的一部分,而
shared_ptr
的删除器是在构造时指定的。 这导致了一些重要的区别:

  • 类型安全性:
    unique_ptr
    提供了更强的类型安全性,因为删除器的类型是在编译时确定的。这可以避免一些运行时错误。
  • 性能:
    unique_ptr
    通常比
    shared_ptr
    更有效率,因为它不需要维护引用计数。此外,如果删除器是一个空函数对象(即,没有任何状态),编译器可以对其进行优化,从而完全消除删除器的开销。
  • 灵活性:
    shared_ptr
    提供了更大的灵活性,因为它允许在运行时指定删除器。这对于需要在不同情况下使用不同删除器的场景非常有用。

选择使用

unique_ptr
还是
shared_ptr
取决于具体的资源管理需求。通常,如果资源的所有权是唯一的,则应该使用
unique_ptr
。 如果资源需要被多个对象共享,则应该使用
shared_ptr

如何处理删除器抛出异常的情况?

如果删除器抛出异常,程序通常会终止。 这是因为在对象销毁过程中抛出异常可能会导致未定义的行为。 为了避免这种情况,应该确保删除器不会抛出异常,或者至少要捕获并处理所有可能抛出的异常。

一种常见的做法是在删除器中使用

try-catch
块来捕获异常并记录错误信息。

#include 
#include 

struct BadFileCloser {
    void operator()(FILE* file) const {
        if (file) {
            if (rand() % 2 == 0) {
                fclose(file);
                std::cout << "File closed.\n";
            } else {
                throw std::runtime_error("Simulated file close error!");
            }
        }
    }
};


int main() {
    FILE* file = fopen("example.txt", "w");
    if (!file) {
        std::cerr << "Failed to open file.\n";
        return 1;
    }

    std::unique_ptr safeFile(file, [](FILE* f) {
        try {
            if (f) {
                fclose(f);
                std::cout << "File closed safely.\n";
            }
        } catch (const std::exception& e) {
            std::cerr << "Exception during file close: " << e.what() << '\n';
            // 可以选择记录错误日志或采取其他补救措施
        } catch (...) {
            std::cerr << "Unknown exception during file close!\n";
        }
    });

    fprintf(safeFile.get(), "This will be closed safely (hopefully).\n");

    return 0;
}

在这个例子中,lambda删除器捕获了

fclose
可能抛出的任何异常,并打印了错误信息。 这可以防止程序意外终止。

请注意,即使捕获了异常,程序的状态也可能是不确定的。 因此,最好设计删除器,使其尽可能避免抛出异常。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
fclose函数的用法
fclose函数的用法

fclose是一个C语言和C++中的标准库函数,用于关闭一个已经打开的文件,是文件操作中非常重要的一个函数,用于将文件流与底层文件系统分离,释放相关的资源。更多关于fclose函数的相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

333

2023.11.30

javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

177

2023.11.23

java中void的含义
java中void的含义

本专题整合了Java中void的相关内容,阅读专题下面的文章了解更多详细内容。

100

2025.11.27

lambda表达式
lambda表达式

Lambda表达式是一种匿名函数的简洁表示方式,它可以在需要函数作为参数的地方使用,并提供了一种更简洁、更灵活的编码方式,其语法为“lambda 参数列表: 表达式”,参数列表是函数的参数,可以包含一个或多个参数,用逗号分隔,表达式是函数的执行体,用于定义函数的具体操作。本专题为大家提供lambda表达式相关的文章、下载、课程内容,供大家免费下载体验。

208

2023.09.15

python lambda函数
python lambda函数

本专题整合了python lambda函数用法详解,阅读专题下面的文章了解更多详细内容。

191

2025.11.08

Python lambda详解
Python lambda详解

本专题整合了Python lambda函数相关教程,阅读下面的文章了解更多详细内容。

55

2026.01.05

数据库Delete用法
数据库Delete用法

数据库Delete用法:1、删除单条记录;2、删除多条记录;3、删除所有记录;4、删除特定条件的记录。更多关于数据库Delete的内容,大家可以访问下面的文章。

278

2023.11.13

drop和delete的区别
drop和delete的区别

drop和delete的区别:1、功能与用途;2、操作对象;3、可逆性;4、空间释放;5、执行速度与效率;6、与其他命令的交互;7、影响的持久性;8、语法和执行;9、触发器与约束;10、事务处理。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

213

2023.12.29

2026赚钱平台入口大全
2026赚钱平台入口大全

2026年最新赚钱平台入口汇总,涵盖任务众包、内容创作、电商运营、技能变现等多类正规渠道,助你轻松开启副业增收之路。阅读专题下面的文章了解更多详细内容。

54

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
黑马云课堂mongodb实操视频教程
黑马云课堂mongodb实操视频教程

共11课时 | 3.1万人学习

DOM操作与实战案例
DOM操作与实战案例

共14课时 | 1.9万人学习

iOS应用UI控件开发基础视频
iOS应用UI控件开发基础视频

共148课时 | 32万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号