MST

星途 面试题库

面试题:C++中std::unique_ptr与自定义删除器结合的高级应用

在C++里,给出一个场景,其中使用std::unique_ptr管理非堆内存资源(例如文件描述符),并实现一个自定义删除器。要求详细说明自定义删除器的设计思路、实现细节,以及它在这种场景下对资源管理的必要性和优势。
34.6万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

场景描述

假设我们要在C++ 中使用文件描述符进行文件操作,并且希望使用std::unique_ptr来管理这个文件描述符,以确保文件描述符在不再需要时能被正确关闭。在Unix - like系统中,文件描述符是一个整数类型,通过open函数打开文件会返回一个文件描述符,使用完后需要通过close函数关闭。

自定义删除器设计思路

  1. 明确功能:自定义删除器的主要功能是在std::unique_ptr销毁其所管理的资源(文件描述符)时,调用合适的函数(如close)来释放该资源。
  2. 参数设计:删除器函数需要接收文件描述符作为参数,以便进行关闭操作。

实现细节

#include <iostream>
#include <memory>
#include <unistd.h> // 包含close函数

// 自定义删除器
struct FileDescriptorDeleter {
    void operator()(int* fd) const {
        if (fd != nullptr) {
            close(*fd);
            delete fd;
        }
    }
};

int main() {
    // 打开文件获取文件描述符
    int* fileDescriptor = new int(open("test.txt", O_RDONLY));
    if (*fileDescriptor == -1) {
        std::cerr << "Failed to open file" << std::endl;
        return 1;
    }

    // 使用std::unique_ptr管理文件描述符,并传入自定义删除器
    std::unique_ptr<int, FileDescriptorDeleter> filePtr(fileDescriptor);

    // 这里可以进行文件操作,例如读取文件内容

    // 当filePtr超出作用域时,自定义删除器会自动调用close关闭文件描述符
    return 0;
}

在上述代码中:

  • 定义了FileDescriptorDeleter结构体,它重载了()运算符,实现了删除逻辑。在operator()中,首先检查文件描述符指针是否为空,不为空则调用close关闭文件描述符,并释放内存。
  • main函数中,通过open函数获取文件描述符,并使用new分配了一个指向该文件描述符的指针。然后使用std::unique_ptr来管理这个指针,并传入自定义删除器FileDescriptorDeleter

必要性和优势

  1. 必要性
    • 异常安全:如果在使用文件描述符的过程中发生异常,手动调用close函数可能会被跳过,导致文件描述符未关闭,产生资源泄漏。而std::unique_ptr结合自定义删除器可以确保无论是否发生异常,文件描述符都会被正确关闭。
    • 遵循RAII原则:RAII(Resource Acquisition Is Initialization)原则要求资源的获取和释放应与对象的生命周期绑定。std::unique_ptr和自定义删除器正是这种原则的体现,将文件描述符的关闭操作与std::unique_ptr对象的析构绑定在一起。
  2. 优势
    • 简洁清晰:代码结构更加简洁,将资源管理逻辑封装在std::unique_ptr和自定义删除器中,使得业务代码更加专注于文件操作本身,而不必担心资源释放的细节。
    • 可移植性:通过自定义删除器,可以将特定平台的资源管理函数(如close)封装起来,使代码在不同平台上具有更好的可移植性,同时也便于维护和修改资源管理逻辑。