0

0

C++中的RAII机制是什么意思?(资源获取即初始化管理资源生命周期)

冰火之心

冰火之心

发布时间:2026-01-13 15:35:19

|

846人浏览过

|

来源于php中文网

原创

RAII是C++通过构造函数获取资源、析构函数释放资源的强制约定,依赖栈对象或智能指针确保析构确定执行;裸指针无法保障异常安全与自动清理,析构函数必须完整正确且配合移动语义避免重复释放。

c++中的raii机制是什么意思?(资源获取即初始化管理资源生命周期)

RAII 不是语法糖,也不是库功能,它是 C++ 用构造函数和析构函数绑定资源生命周期的强制约定。只要你定义了类,并在构造函数里获取资源(比如 newfopenpthread_mutex_init),在析构函数里释放(deletefclosepthread_mutex_destroy),就天然符合 RAII。

为什么必须用对象或智能指针,不能裸指针 new 出来?

裸指针无法保证析构执行:异常抛出、提前 return、忘记 delete 都会导致资源泄漏。RAII 的核心保障来自 C++ 对栈对象生命周期的确定性管理——作用域结束时自动调用析构函数。

  • 栈对象:最直接,std::ifstream f("a.txt"); 离开作用域自动关闭文件
  • std::unique_ptr / std::shared_ptr:堆上资源也能享受 RAII,前提是自定义删除器(例如 std::unique_ptr
  • 绝不能写 FILE* f = fopen(...); 然后靠人工配对 fclose —— 这已经脱离 RAII

常见误用:把 RAII 当成“只要写了析构函数就行”

析构函数里没做清理,或者清理逻辑有缺陷(比如没检查空指针、忽略返回值、未处理部分失败),照样泄漏或崩溃。RAII 的有效性完全依赖析构函数的正确性和完整性。

  • 错误示例:
    class BadHandle {
        int fd_;
    public:
        BadHandle(const char* path) { fd_ = open(path, O_RDONLY); }
        ~BadHandle() { /* 忘了 close(fd_) */ } // 资源泄漏
    };
  • 正确示例:
    class FileHandle {
        int fd_;
    public:
        FileHandle(const char* path) : fd_(open(path, O_RDONLY)) {
            if (fd_ == -1) throw std::system_error(errno, std::generic_category());
        }
        ~FileHandle() { if (fd_ != -1) close(fd_); }
        FileHandle(const FileHandle&) = delete;
        FileHandle& operator=(const FileHandle&) = delete;
    };

RAII 和 move 语义怎么配合?

资源只能归属一个所有者。如果类支持移动(比如 std::vectorstd::unique_ptr),必须显式禁用拷贝、实现移动构造/赋值,并在移动后将原对象资源置为无效状态(如把 fd_ 设为 -1),否则析构时重复释放会 crash。

萝卜简历
萝卜简历

免费在线AI简历制作工具,帮助求职者轻松完成简历制作。

下载

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

  • 移动后不置空 fd_ → 两个对象析构都调 close(-1) 或更糟的 close(已关闭的 fd)
  • 没删除拷贝构造函数 → 可能意外触发浅拷贝,导致双析构
  • 标准库类型(如 std::mutex)本身不可拷贝不可移动,就是刻意为之的设计

RAII 看似简单,真正落地时最难的是边界情况:异常安全、移动后的状态一致性、多线程下析构是否可重入。别只盯着“有没有析构函数”,要盯住“析构函数会不会被跳过、会不会被重复调、会不会在错误状态下被调”。

相关专题

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

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

326

2023.11.30

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

387

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

571

2023.08.10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

387

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

571

2023.08.10

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

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

480

2023.08.10

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

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

143

2025.12.24

空指针异常处理
空指针异常处理

本专题整合了空指针异常解决方法,阅读专题下面的文章了解更多详细内容。

22

2025.11.16

Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

36

2026.01.14

热门下载

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

精品课程

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

共32课时 | 3.7万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

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

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