RAII
是指
C++
语言中资源管理的一种方式,简单而又不会出什么岔子,英文全拼也说明了他的用法,
它是“
R
esource A
cquisition I
s I
nitialization
”的首字母缩写
首先让我们来明确资源的概念,在计算机系统中,资源是数量有限且对系统正常运转具有一定作用的元素。比如,内存,文件句柄,网络套接字(
network sockets
),互斥锁(
mutex locks
)等等,它们都属于系统资源。由于资源的数量不是无限的,有的资源甚至在整个系统中仅有一份,因此我们在使用资源时必须严格遵循的步骤是:
1.
获取资源
2.
使用资源
3.
释放资源
例如在下面的
UseFile
函数中:
void UseFile(char const* fn)
{
FILE* f = fopen(fn, "r"); // 获取资源
// 在此处使用文件句柄f...代码 // 使用资源
fclose(f); // 释放资源
}
调用
fopen()
打开文件就是获取文件句柄资源,操作完成之后,调用
fclose()
关闭文件就是释放该资源。资源的释放工作至关重要,如果只获取而不释放,那么资源最终会被耗尽。上面的代码是否能够保证在任何情况下都调用
fclose
函数呢?请考虑如下情况:
void UseFile(char const* fn)
{
FILE* f = fopen(fn, "r"); // 获取资源
// ........... 使用资源代码
if (!g()) return; // 如果操作g失败!
// ...
if (!h()) return; // 如果操作h失败!
// ...
fclose(f); // 释放资源
}
但是在使用文件
f
的过程中,因某些操作失败而造成函数提前返回的现象经常出现。这时函数
UseFile
的执行流程将变为:
![](/admin/blogs/data:image/png;base64,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)
很明显,这里忘记了一个重要的步骤:在操作
g
或
h
失败之后,
UseFile
函数必须首先调用
fclose()
关闭文件,然后才能返回其调用者,否则会造成资源泄漏。因此,需要将
UseFile
函数修改为:
void UseFile(char const* fn)
{
FILE* f = fopen(fn, "r"); // 获取资源
// 使用资源
if (!g()) { fclose(f); return; }
// ...
if (!h()) { fclose(f); return; }
// ...
fclose(f); // 释放资源
}
现在的问题是:用于释放资源的代码
fclose(f)
需要在不同的位置重复书写多次。如果再加入异常处理,情况会变得更加复杂。例如,在文件
f
的使用过程中,程序可能会抛出异常:
void UseFile(char const* fn)
{
FILE* f = fopen(fn, "r"); // 获取资源
// 使用资源
try {
if (!g()) { fclose(f); return; }
// ...
if (!h()) { fclose(f); return; }
// ...
}
catch (...) {
fclose(f); // 释放资源
throw;
}
fclose(f); // 释放资源
}
我们必须依靠
catch(...)
来捕获所有的异常,关闭文件
f
,
并重新抛出该异常。随着控制流程复杂度的增加,需要添加资源释放代码的位置会越来越多。如果资源的数量还不止一个,那么程序员就更加难于招架了。可以想象
这种做法的后果是:代码臃肿,效率下降,更重要的是,程序的可理解性和可维护性明显降低。是否存在一种方法可以实现资源管理的自动化呢?答案是肯定的。假
设
UseResources
函数要用到
n
个资源,则进行资源管理的一般模式为:
void UseResources() // 注意不要使用指针(智能指针可以)
{
// 获取资源1
// ...
// 获取资源n
// 使用这些资源
// 释放资源n
// ...
// 释放资源1
}
不难看出资源管理技术的关键在于:要保证资源的释放顺序与获取顺序严格相反。这自然使我们联想到局部对象的创建和销毁过程。在
C++
中,定义在栈空间上的局部对象称为自动存储(
automatic memory
)对象。管理局部对象的任务非常简单,因为它们的创建和销毁工作是由系统自动完成的。我们只需在某个作用域(
scope
)中定义局部对象(这时系统自动调用构造函数以创建对象),然后就可以放心大胆地使用之,而不必担心有关善后工作;当控制流程超出这个作用域的范围时,系统会自动调用析构函数,从而销毁该对象。
如果系统中的资源也具有如同局部对象一样的特性,自动获取,自动释放,那该有多么美妙啊!。事实上,您的想法已经与
RAII
不谋而合了。既然类是
C++
中的主要抽象工具,那么就将资源抽象为类,用局部对象来表示资源,把管理资源的任务转化为管理局部对象的任务。这就是
RAII
惯用法的真谛!可以毫不夸张地说,
RAII
有效地实现了
C++
资源管理的自动化。例如,我们可以将文件句柄
FILE
抽象为
FileHandle
类:
class FileHandle {
public:
FileHandle(char const* n, char const* a) { p = fopen(n, a); }
~FileHandle() { fclose(p); }
private:
FileHandle(FileHandle const&);
FileHandle& operator= (FileHandle const&); // 禁止拷贝操作
FILE *p;
};
FileHandle
类的构造函数调用
fopen()
获取资源;
FileHandle
类的析构函数调用
fclose()
释放资源。请注意,考虑到
FileHandle
对象代表一种资源,它并不具有拷贝语义,因此我们将拷贝构造函数和赋值运算符声明为私有成员。如果利用
FileHandle
类的局部对象表示文件句柄资源,那么前面的
UseFile
函数便可简化为:
void UseFile(char const* fn)
{
FileHandle file(fn, "r");
// 在此处使用文件句柄f...
// 超出此作用域时,系统会自动调用file的析构函数,从而释放资源
}
现在我们就不必担心隐藏在代码之中的
return
语句了;不管函数是正常结束,还是提前返回,系统都必须“乖乖地”调用
f
的析构函数,资源一定能被释放。
且慢!如若使用文件
file
的代码中有异常抛出,难道析构函数还会被调用吗?此时
RAII
还能如此奏效吗?问得好。事实上,当一个异常抛出之后,系统沿着函数调用栈,向上寻找
catch
子句的过程,称为栈辗转开解(
stack unwinding
)。
C++
标准规定,在辗转开解函数调用栈的过程中,系统必须确保调用所有已创建起来的局部对象的析构函数。例如:
void Foo()
{
FileHandle file1("n1.txt", "r");
FileHandle file2("n2.txt", "w");
Bar(); // 可能抛出异常
FileHandle file3("n3.txt", "rw")
}
当
Foo()
调用
Bar()
时,局部对象
file1
和
file2
已经在
Foo
的函数调用栈中创建完毕,而
file3
却尚未创建。如果
Bar()
抛出异常,那么
file2
和
file1
的析构函数会被先后调用(注意:析构函数的调用顺序与构造函数相反);由于此时栈中尚不存在
file3
对象,因此它的析构函数不会被调用。只有当一个对象的构造函数执行完毕之后,我们才认为该对象的创建工作已经完成。栈辗转开解过程仅调用那些业已创建的对象的析构函数。
RAII
惯用法同样适用于需要管理多个资源的复杂对象。例如,
Widget
类的构造函数要获取两个资源:文件
myFile
和互斥锁
myLock
。每个资源的获取都有可能失败并且抛出异常。为了正常使用
Widget
对象,这里我们必须维护一个不变式(
invariant
):当调用构造函数时,要么两个资源全都获得,对象创建成功;要么两个资源都没得到,对象创建失败。获取了文件而没有得到互斥锁的情况永远不能出现,也就是说,不允许建立
Widget
对象的“半成品”。如果将
RAII
惯用法应用于成员对象,那么我们就可以实现这个不变式:
class Widget {
public:
Widget(char const* myFile, char const* myLock)
: file_(myFile), // 获取文件myFile
lock_(myLock) // 获取互斥锁myLock
{}
// ...
private:
FileHandle file_;
LockHandle lock_;
};
FileHandle
和
LockHandle
类的对象作为
Widget
类的数据成员,分别表示需要获取的文件和互斥锁。资源的获取过程就是两个成员对象的初始化过程。在此系统会自动地为我们进行资源管理,程序员不必显式地添加任何异常处理代码。
RAII
的本质
内容是用对象代表资源,把管理资源的任务转化为管理对象的任务,将资源的获取和释放与对象的构造和析构对应起来,从而确保在对象的生存期内资源始终有效,对象销毁时资源必被释放。换句话说,拥有对象就等于拥有资源,对象存在则资源必定存在。
由此可见,
RAII
惯用法是进行资源管理的有力武器。
C++
程序员
依靠
RAII
写出的代码不仅简洁优雅,而且做到了异常安全。
本文截取自:http://www.cnblogs.com/hsinwang/articles/214663.html
分享到:
相关推荐
1. **全面支持C++标准**:DEV-C++遵循最新的C++编程标准,允许开发者利用现代C++特性如模板、STL(标准模板库)、RAII(资源获取即初始化)等进行编程。 2. **友好的中文界面**:对于中文用户,DEV-C++提供了本地化...
RAII是C++中一种强大的资源管理技术,它通过将资源管理封装在对象的生命周期中,简化了资源管理,提高了代码的安全性和可维护性。通过使用RAII,开发者可以减少因资源管理不当导致的内存泄漏和其他问题,从而编写出...
标题 "C语言复习1-C++.zip" 暗示了这是一个关于C语言学习资料的压缩包,其中可能包含了与C语言基础、进阶概念以及与C++相关的学习资源。C语言是计算机科学的基础,而C++是C语言的增强版,引入了面向对象编程的概念。...
RAII是C++中一种强大的资源管理技术,它通过将资源的生命周期与对象的生命周期绑定,确保资源的正确获取和释放。这种模式不仅提高了代码的健壮性,还简化了资源管理的复杂性。掌握RAII原则,可以帮助开发者编写更...
- **RAII(Resource Acquisition Is Initialization)**:理解RAII原则,以确保资源在生命周期中的正确管理。 - **C++11及更高版本的新特性**:学习并运用C++11及后续版本引入的新功能,如lambda表达式、右值引用...
RAII则可以帮助管理资源,避免内存泄漏。 此外,为了提高用户交互体验,通常会结合图形用户界面(GUI)库,如Qt或wxWidgets,来构建系统前端。这需要理解事件驱动编程模型,以及如何在C++中集成GUI库。 在实际开发...
6. **智能指针**:C++11引入的智能指针(如shared_ptr、unique_ptr等)解决了原始指针可能导致的内存管理问题,使得资源管理更加安全。 7. **Lambda表达式**:C++11引入的lambda表达式简化了函数对象的定义,使得在...
4. **资源管理**:掌握智能指针(C++)和RAII(资源获取即初始化,C++特有)来自动管理资源,避免资源泄露。 ### 代码优化与调试 1. **性能优化**:理解编译器优化选项,学会使用性能分析工具来分析代码瓶颈,并...
7. **异常安全编程**:掌握异常传播和资源管理策略,如 RAII(Resource Acquisition Is Initialization)原则。 8. **多线程编程**:了解 C++11 及以后版本的并发和线程库,实现高效的多线程应用。 9. **C++ 标准库*...
8. **RAII(Resource Acquisition Is Initialization)**:C++鼓励使用RAII技术,即将资源的生命周期绑定到对象的生命周期,确保资源的正确管理。 9. **C++11及以后的更新**:C++11、C++14、C++17和C++20等新标准...
15. **资源管理与优化**:了解并应用资源管理技术(如智能指针、RAII等),可以有效地控制内存使用,避免资源泄露,提高程序性能。 16. **跨平台编程**:熟悉C++的跨平台特性,能够使得所编写的程序在不同的操作...
- **策略**:采用“资源获取即初始化”的原则(RAII),确保资源在对象构造时获得,在析构时释放。 - **实施**:利用构造函数获取资源,并确保即使发生异常也能通过析构函数释放资源。 **5.3 Item 11:禁止异常信息...
- **智能指针**:学习unique_ptr、shared_ptr和weak_ptr,理解内存管理和RAII(Resource Acquisition Is Initialization)原则。 - **Lambda表达式**:了解并使用C++11引入的Lambda函数,提升代码可读性和简洁性。...
在C++编程中,内存管理是一项关键任务,尤其是在大型项目中。内存泄漏是常见的编程错误,它发生在程序分配了内存但未能正确释放时。Visual Studio 2019(VS2019)提供了一些强大的工具来帮助开发者检测和解决这类...
2. **智能指针**:如`std::unique_ptr`, `std::shared_ptr`和`std::weak_ptr`,这些智能指针在C++11及更高版本中引入,用于自动管理内存,防止资源泄露。 3. **内存对齐**:讨论了内存对齐的概念,它影响数据结构的...
14. **RAII(Resource Acquisition Is Initialization)**:C++的资源管理策略,通过对象生命周期管理资源,避免资源泄露。 15. **C++11及以后的更新**:包括lambda表达式、右值引用、智能指针等新特性,使得C++...
4. **智能指针与RAII(Resource Acquisition Is Initialization)**:智能指针是RAII原则的典型应用,资源在对象构造时获取,在对象析构时释放,确保资源管理的正确性。 5. **智能指针的转换**:在某些情况下,不同...
11. **RAII(Resource Acquisition Is Initialization)**:资源获取即初始化,是一种编程策略,常用于管理生命周期较短的资源,确保资源在不再需要时被正确释放。 12. **C++11/14/17/20新特性**:如lambda表达式、...
14. **异常安全性和资源管理**:讲解如何确保在异常发生时正确释放资源,以及RAII(Resource Acquisition Is Initialization)原则。 15. **C++11新特性**:如果习题答案涵盖C++11,那么可能会涉及lambda表达式、...
"C++资源管理器源程序"可能是一个用于学习或实际项目中的工具,它允许用户查看、操作和管理各种类型的资源。这个压缩包文件包含了实现这一功能的源代码,我们可以从中学习到C++中关于资源管理的一些核心概念和技术。...