RAII(Resource Acquisition Is Initialization 资源获得即初始化)是管理资源的一种方式,它在构造对象时初始化资源,析构对象时释放资源,有时也把这2个过程分为RAII和RRID(Resource Release Is Destruction 资源释放即析构),这通常需要语言支持。
大部分语言都支持RAII,RRID则有少数语言不支持,这些语言无法在域结束时自动销毁栈上分配的对象,java就是这种。
先来看看一个简单的JDBC调用过程:
Connection conn = null;
Statement stmt = null;
ResultSet rset = null;
try{
conn = createConnection();
stmt = conn.prepareStatement("SELECT * FROM USERS");
rset = stmt.executeQuery();
// 使用rset ...
}finally{
if(rset!=null)rset.close();
if(stmt!=null)stmt.close();
if(conn!=null)conn.close();
}
C++中在栈上分配的对象离开它的作用域时会自动调用析构函数,类似功能的代码大概只要写成这样就可以了:
conn = createConnection();
stmt = conn.prepareStatement("SELECT * FROM USERS");
rset = stmt.executeQuery();
// 使用rset ...
如果析构函数中调用了close,它会在这几个变量离开作用域时按它们声明的相反顺序调用析构函数,也就达到了按这个顺序进行close的效果。
考虑到上面的Connection/Statement/ResultSet都是接口,如果在C++中也来这样操作接口的话,同样无法享受这种便利,因为在C++中用接口来操作意味着你必须使用指针,不幸的是指针没有析构函数,它只是简单类型。不过我们可以把这个工作委托给另一个对象,由这个对象来调用析构函数,你可以使用auto_ptr。或者可以参考ScopeGuard(由Andrei Alexandrescu & Petru Marginean 实现),它可以调用一个指定的方法,而不限于析构一个对象。C++能做到这些,因为C++栈上分配的对象在离开作用域时会自动析构,即便是发生异常也风雨无阻,别在析构函数中再抛异常就行了。
auto_ptr版本:
auto_ptr<Connection> conn (createConnection());
auto_ptr<Statement> stmt (conn->prepareStatement("SELECT * FROM USERS"))
auto_ptr<ResultSet> rset (stmt->executeQuery());
// 使用rset ...
ScopeGuard版本:
template <class T>
void ReleaseObject(T* obj){
delete (T*)obj;
}
Connection* conn = createConnection();
ScopeGuard connGuard(ReleaseObject<Connection>, conn);
Statement* stmt = conn->prepareStatement("SELECT * FROM USERS");
ScopeGuard connGuard(ReleaseObject<Statement>, stmt);
ResultSet* rset = stmt->executeQuery();
ScopeGuard connGuard(ReleaseObject<ResultSet>, rset);
// 使用rset ...
ScopeGuard使用起来稍麻烦,原因是它不是为了析构对象而设计的,它是为了在自己析构时,执行一个指定任务,用起来很灵活。
C#使用using来达到相同的功能,不熟悉也不用它,就不去找代码了。
如果用ruby来做,我想可能是这样吧:
createConnection do |conn|
conn.preparedStatement("SELECT * FROM USERS") do |stmt|
rset = stmt.executeQuery();
# 使用 rset ...
end
end
由于代码都在块中,只需要在调用块的前后初始化及释放就可以了,从这点上来说,java也可以这样做,代码丑了点而已。。。
最后看看D语言是怎么做的吧:
scope Connection conn = createConnection();
scope Statement stmt = conn.prepareStatement("SELECT * FROM USERS");
scope ResultSet rset = stmt.executeQuery();
// 使用 rset ...
上面的Connection/Statement/ResultSet都可以是接口,作为“C++的改良者”,看起来至少在语法上它有所改进。可以看到它所用的代码不如C++/java这么多,也不需要C#和ruby这样构造出一“块”代码。
[注:上面用的scope关键字,原来是用auto,0.174中似乎说RAII中使用的auto应该被scope代替。]
D语言还从语言层次上提供了scope guard:
Connection conn = createConnection();
scope(exit) conn.close();
Statement stmt = conn.prepareStatement("SELECT * FROM USERS");
scope(exit) stmt.close();
ResultSet rset = stmt.executeQuery();
scope(exit) rset.close();
// 使用 rset
分享到:
相关推荐
- 还会介绍如何配置文本编辑器或IDE(集成开发环境)来支持D语言的开发。 3. **编写第一个程序**: - 本部分通过一个简单的“Hello, World!”程序示例,让读者亲自动手实践。 - 这有助于理解D语言的基本语法结构...
5. **范围(Scope)**:D语言的范围解析运算符(`~=`)用于定义作用域,这可以自动清理资源,类似于C++的RAII(Resource Acquisition Is Initialization)。 6. **异常处理**:D语言支持异常处理,允许通过`try-...
4. 内存管理:D语言内置垃圾回收机制,同时也允许手动内存管理,提供了丰富的内存安全特性,如智能指针和RAII(Resource Acquisition Is Initialization)。 5. 错误处理:D语言采用异常处理机制来捕获运行时错误,...
D语言引入了**RAII**(Resource Acquisition Is Initialization)的概念,通过构造函数和析构函数自动管理资源的生命周期,降低了内存泄漏的风险。 ##### 3.5 性能优化 - **零成本抽象**:D语言实现了零成本抽象,...
它是一种静态类型的、编译式的、通用的、大小写敏感的、不仅支持过程化编程,也支持面向对象编程的语言。C++ 的主要特点包括: 1. **面向对象**:C++ 提供了类和对象的概念,使得代码可以被组织成可重用的模块。类...
科纳克(Konark)是一款基于C++语言开发的2D游戏引擎,专为游戏开发者提供高效、灵活且易用的工具,以创建丰富多彩的2D游戏世界。C++作为底层编程语言,使得Konark在性能上具有显著优势,同时其高度的可定制性和面向...
1. **C++基础**:C++是一种静态类型的、编译式的、通用的、大小写敏感的、不仅支持过程化编程,也支持面向对象编程的程序设计语言。它继承了C语言的特性,并增加了类、模板、异常处理等面向对象的特性。 2. **数据...
它是一个开源的、跨平台的编译器套件,支持C、C++、Objective-C、Fortran、Ada、Go、D等多种编程语言。GCC不仅包括前端编译器,还包含后端链接器和库,使得开发者能够在各种操作系统和硬件平台上构建和运行程序。 *...
【标题】"Bumble_D" 是一个项目或软件的代号,可能是一个使用 C++ 编程语言开发的应用程序。由于信息有限,我们主要从 C++ 的核心概念和编程实践来探讨相关知识点。 C++ 是一种强类型、静态类型的编程语言,它在 C ...
7. **内存管理**:理解动态内存分配、智能指针(如std::unique_ptr、std::shared_ptr)以及RAII(Resource Acquisition Is Initialization)原则,以避免内存泄漏。 8. **并发编程**:简述C++11及后续版本提供的...
“bndr-engine”是一个专为Windows x64平台设计的游戏引擎,主要用C++语言编写,专注于2D游戏开发。游戏引擎是游戏开发的核心,它提供了图形渲染、物理模拟、音频处理、输入管理等多种功能,帮助开发者快速构建游戏...
现代C++支持模板元编程、智能指针、RAII(Resource Acquisition Is Initialization)等高级特性,这些都使得Morpheus在内存管理、性能优化和代码安全性方面具有优势。 二、Game Boy Advance与Nintendo DS硬件特性...
在C语言中,`defer`语句是一...在C++中,可以使用RAII(Resource Acquisition Is Initialization)原则和智能指针来更好地管理资源,而在Go等其他语言中,`defer`是语言内置的一部分,提供了更强大的保障和简洁的语法。
- **答案**:C++没有提供类似Java中的finally块,但可以通过RAII(资源获取即初始化)模式来实现相似的功能。通过确保资源在对象生命周期结束时释放,可以达到与finally相同的效果。 #### 2.8 为何没有提供auto_...
- 在适当的地方使用RAII(Resource Acquisition Is Initialization)原则。 - **异常处理的注意事项:** - 在C++中,使用异常处理可以更好地管理程序中的错误。 - 需要注意的是,抛出异常后的程序状态可能会变得...
OpenHadouken是用C++语言编写的,C++是一种强类型、静态类型的通用编程语言,以其高效性、灵活性和强大的系统级编程能力而闻名。它不仅支持面向过程编程,还引入了面向对象的概念,使得代码更加模块化和易于维护。...
7. **C++11及以后的标准**:自C++11以来,C++引入了许多新特性,如lambda表达式、右值引用、auto关键字、类型推断、强类型枚举、并发支持等,进一步提升了语言的现代性和效率。 8. **内存管理**:C++允许直接操作...
- **D&B&FWAlgorithm** - Dijkstra 算法、Bellman-Ford 算法和 Floyd-Warshall 算法分别用于解决单源最短路径问题、带负权边的单源最短路径问题和任意两点间的最短路径问题。 - **应用** - 图的应用非常广泛,包括...