0

0

智能指针能否用于管理文件描述符 自定义删除器封装系统资源

P粉602998670

P粉602998670

发布时间:2025-08-12 14:33:01

|

528人浏览过

|

来源于php中文网

原创

是的,智能指针能用于管理文件描述符。1. 通过自定义删除器(如fdcloser)可确保文件描述符在对象析构时自动关闭,避免资源泄漏;2. std::unique_ptr适用于独占所有权场景,支持通过std::move进行所有权转移;3. std::shared_ptr适用于共享所有权场景,但需注意引用计数开销和循环引用风险;4. 自定义删除器不仅适用于文件描述符,还可用于管理互斥锁、套接字、数据库连接等非内存资源。

智能指针能否用于管理文件描述符 自定义删除器封装系统资源

智能指针能用于管理文件描述符,通过自定义删除器可以优雅地封装系统资源,避免手动管理带来的风险。

智能指针能否用于管理文件描述符 自定义删除器封装系统资源

解决方案:

智能指针能否用于管理文件描述符 自定义删除器封装系统资源

智能指针,特别是

std::unique_ptr
std::shared_ptr
,是 C++ 中管理动态分配资源的利器。 它们的核心思想是 RAII (Resource Acquisition Is Initialization),即资源在对象构造时获取,在对象析构时释放。 这种机制天然适合管理文件描述符这类系统资源。

关键在于自定义删除器 (custom deleter)。 默认情况下,

std::unique_ptr
std::shared_ptr
使用
delete
运算符来释放资源。 但对于文件描述符,我们需要使用
close()
函数。 因此,我们需要提供一个自定义的删除器函数或函数对象。

智能指针能否用于管理文件描述符 自定义删除器封装系统资源

以下是一个使用

std::unique_ptr
管理文件描述符的示例:

#include 
#include 
#include 
#include 

// 自定义删除器
struct FDCloser {
    void operator()(int fd) {
        if (fd != -1) { // 确保文件描述符有效
            if (close(fd) == -1) {
                perror("close"); // 错误处理
            } else {
                std::cout << "File descriptor " << fd << " closed." << std::endl;
            }
        }
    }
};

int main() {
    // 打开文件,如果失败,返回 -1
    int fd = open("example.txt", O_RDWR | O_CREAT, 0666);
    if (fd == -1) {
        perror("open");
        return 1;
    }

    // 使用 unique_ptr 管理文件描述符
    std::unique_ptr file_descriptor(fd, FDCloser());

    // 使用文件描述符进行读写操作...
    // 例如,写入一些数据
    const char* data = "Hello, world!";
    ssize_t bytes_written = write(file_descriptor.get(), data, strlen(data));
    if (bytes_written == -1) {
        perror("write");
        return 1;
    }

    std::cout << "Wrote " << bytes_written << " bytes to file." << std::endl;

    // unique_ptr 在超出作用域时会自动关闭文件描述符
    return 0;
}

在这个例子中,

FDCloser
是一个函数对象,它接受一个文件描述符作为参数,并调用
close()
函数来关闭它。
std::unique_ptr
会在销毁时调用这个删除器,确保文件描述符被正确关闭。 重要的是,即使程序在
unique_ptr
销毁之前抛出异常,
close()
也会被调用,这避免了资源泄漏。

使用

std::shared_ptr
的方式类似,只是
shared_ptr
允许多个指针共享同一个文件描述符的所有权。 这在某些并发场景下可能很有用,但需要仔细考虑所有权和生命周期管理。

Build AI
Build AI

为您的业务构建自己的AI应用程序。不需要任何技术技能。

下载

智能指针确实提供了一种安全且方便的方式来管理文件描述符,避免了手动

close()
调用可能导致的错误。 但是,错误处理仍然很重要。 例如,在删除器中检查
close()
的返回值并处理错误情况是至关重要的。

自定义删除器在哪些场景下特别有用?

自定义删除器在管理任何非内存资源时都非常有用。 除了文件描述符,还可以用于管理互斥锁、套接字、数据库连接等。 任何需要特定释放函数的资源都可以通过自定义删除器与智能指针一起使用。 比如管理一个使用

pthread_mutex_t
的互斥锁,就需要自定义删除器来调用
pthread_mutex_destroy
来释放资源。

#include 
#include 
#include 

struct MutexCloser {
    void operator()(pthread_mutex_t* mutex) {
        if (mutex != nullptr) {
            int result = pthread_mutex_destroy(mutex);
            if (result != 0) {
                std::cerr << "Error destroying mutex: " << result << std::endl;
            } else {
                std::cout << "Mutex destroyed." << std::endl;
            }
        }
    }
};

int main() {
    std::unique_ptr mutex(new pthread_mutex_t);

    if (pthread_mutex_init(mutex.get(), nullptr) != 0) {
        std::cerr << "Error initializing mutex." << std::endl;
        return 1;
    }

    // 使用互斥锁...
    pthread_mutex_lock(mutex.get());
    std::cout << "Mutex locked." << std::endl;
    pthread_mutex_unlock(mutex.get());
    std::cout << "Mutex unlocked." << std::endl;

    // mutex 在超出作用域时会自动销毁互斥锁
    return 0;
}

如何处理文件描述符的所有权转移?

文件描述符的所有权转移需要谨慎处理,尤其是在多线程环境中。 使用

std::unique_ptr
可以很方便地进行所有权转移,因为
unique_ptr
明确表示独占所有权。 可以使用
std::move
将所有权从一个
unique_ptr
转移到另一个
unique_ptr

#include 
#include 
#include 
#include 

struct FDCloser {
    void operator()(int fd) {
        if (fd != -1) {
            if (close(fd) == -1) {
                perror("close");
            } else {
                std::cout << "File descriptor " << fd << " closed." << std::endl;
            }
        }
    }
};

std::unique_ptr create_file_descriptor(const char* filename) {
    int fd = open(filename, O_RDWR | O_CREAT, 0666);
    if (fd == -1) {
        perror("open");
        return nullptr; // 返回空指针表示错误
    }
    return std::unique_ptr(fd, FDCloser());
}

int main() {
    // 创建一个 unique_ptr,拥有文件描述符的所有权
    std::unique_ptr fd_owner = create_file_descriptor("example.txt");

    if (fd_owner == nullptr) {
        std::cerr << "Failed to create file descriptor." << std::endl;
        return 1;
    }

    // 将所有权转移到另一个 unique_ptr
    std::unique_ptr another_fd_owner = std::move(fd_owner);

    // 现在 fd_owner 不再拥有文件描述符的所有权
    // 只有 another_fd_owner 拥有所有权

    // 使用 another_fd_owner 进行操作
    const char* data = "Hello from another owner!";
    ssize_t bytes_written = write(another_fd_owner.get(), data, strlen(data));
    if (bytes_written == -1) {
        perror("write");
        return 1;
    }

    std::cout << "Wrote " << bytes_written << " bytes to file." << std::endl;

    // another_fd_owner 在超出作用域时会自动关闭文件描述符
    return 0;
}

如果需要共享所有权,可以使用

std::shared_ptr
。 但需要注意的是,
shared_ptr
的开销比
unique_ptr
略高,因为它需要维护一个引用计数。 此外,在使用
shared_ptr
管理文件描述符时,需要特别小心避免循环引用,否则可能导致资源泄漏。

智能指针和文件描述符结合使用,能有效提高代码的安全性和可维护性,值得在项目中推广。

相关专题

更多
resource是什么文件
resource是什么文件

Resource文件是一种特殊类型的文件,它通常用于存储应用程序或操作系统中的各种资源信息。它们在应用程序开发中起着关键作用,并在跨平台开发和国际化方面提供支持。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

140

2023.12.20

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1435

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

222

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

84

2025.10.17

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

469

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

106

2025.12.24

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

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

266

2023.11.13

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

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

206

2023.12.29

vlookup函数使用大全
vlookup函数使用大全

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

28

2025.12.30

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Pandas 教程
Pandas 教程

共15课时 | 0.9万人学习

微信小程序开发之API篇
微信小程序开发之API篇

共15课时 | 1.2万人学习

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

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