c++学习-RAII初识
来源:互联网 发布:数据分析 市场 编辑:程序博客网 时间:2024/06/11 18:56
本文主要记载今天早上读到的两篇blog的一些读书笔记。参考链接如下:
[C++中的RAII机制]
[RAII惯用法:C++资源管理的利器]
基本概念
1.什么是RAII(Resource Acquisition Is Initialization)?
中文可将其翻译为“资源获取就是初始化”。当然,这句话肯定并没有揭示出背后本质的思路。
Bjarne这样写道:使用局部对象管理资源的技术通常称为“资源获取就是初始化”
2 . RAII通常的做法是什么?
RAII的做法是使用一个对象(用对象来管理资源申请、资源使用、资源释放),在其构造时获取对应的资源,在对象生命期内控制对资源的访问,使之始终保持有效,最后在对象析构的时候,释放构造时获取的资源。简言之,对象管理资源,构造的时候申请资源,析构的时候释放资源.
3 . 为什么RAII要这么做,它背后的设计思想是什么?
在C++中,定义在栈空间上的局部对象称为自动存储(automatic memory)对象。管理局部对象的任务非常简单,因为它们的创建和销毁工作是由系统自动完成的。我们只需在某个作用域(scope)中定义局部对象(这时系统自动调用构造函数以创建对象),然后就可以放心大胆地使用之,而不必担心有关善后工作;当控制流程超出这个作用域的范围时,系统会自动调用析构函数,从而销毁该对象。
读者可能会说:如果系统中的资源也具有如同局部对象一样的特性,自动获取,自动释放,那该有多么美妙啊!。事实上,您的想法已经与RAII不谋而合了。既然类是C++中的主要抽象工具,那么就将资源抽象为类,用局部对象来表示资源,把管理资源的任务转化为管理局部对象的任务。这就是RAII惯用法的真谛!
简言之,栈对象由系统自动管理,资源需要人工管理。从而将资源抽象为栈对象,把原来需要人工管理的资源变为由系统自动管理的栈对象。
一个简单例子
// 错误代码#include <stdio.h>#include <assert.h>void use_file( const char* file_name, const char* mode ){ char buffer[128]; FILE* pfile = NULL; pfile = fopen( file_name, mode ); if(pfile) return; // 这个地方不小心给写错了!正确的应该是if(!pfile),这样文件已经打开,但是没有关闭就退出了!资源泄露 while( !feof(pfile) ){ if( fgets(buffer, 100, pfile) == NULL ) break; fputs( buffer, stdout ); } fclose(pfile);}int main(){ const char* file = "readme.txt"; use_file( file, "r" ); return 0;}
下面的代码将FILE* pfile资源抽象为一个类,FileHandle代表文件句柄类,管理文件句柄资源。
// 正确代码#include <stdio.h>#include <assert.h>#include <iostream>class FileHandle {public: FileHandle( const char* file, const char* mod ) { pfile = fopen( file, mod ); std::cout << "FileHandler(const char*, const char* mod) called." << std::endl; } ~FileHandle(){ fclose( pfile ); std::cout << "~FileHandle() called." << std::endl; } FILE* get() const { return pfile; }private: // No copying allowed FileHandle( const FileHandle& rhs ); FileHandle& operator=( const FileHandle& rhs );private: FILE* pfile;};void use_file( const char* file_name, const char* mode ){ char buffer[128]; FileHandle file( file_name, mode ); if( file.get() ) return; // 还是写错了,程序提前退出 while( !feof(file.get()) ){ if( fgets(buffer, 100, file.get()) == NULL ) break; fputs( buffer, stdout ); }}int main(){ const char* file = "readme.txt"; use_file( file, "r" ); return 0;}/*FileHandler(const char*, const char* mod) called.~FileHandle() called.*/
注意上面的代码,在释放资源前函数异常退出了,对于之前的代码,没有办法释放资源的。但是,此时应经正确释放了资源。
请注意,考虑到FileHandle对象代表一种资源,它并不具有拷贝语义,因此我们将拷贝构造函数和赋值运算符声明为私有成员
总结
RAII的本质内容是用对象代表资源,把管理资源的任务转化为管理对象的任务,将资源的获取和释放与对象的构造和析构对应起来,从而确保在对象的生存期内资源始终有效,对象销毁时资源一定会被释放。说白了,就是拥有了对象,就拥有了资源,对象在,资源则在。
- c++学习-RAII初识
- C++ RAII
- C++之RAII学习
- [C学习]指针初识
- RAII
- RAII
- RAII
- RAII
- RAII
- RAII
- RAII
- RAII
- RAII
- RAII
- RAII
- RAII
- c语言学习笔记--初识c
- object-c学习:初识object-c
- HDU 3874 Necklace&&HDU 3333 Turing Tree(求一些区间l~r中的数去重后的和)
- Red and Black
- Qt5基本教程
- Win10 必备的卸载利器 IObit Uninstaller 6
- 回溯法求无向图染色
- c++学习-RAII初识
- 【51Nod1154】回文串划分
- share + idds
- activeMQ消息详解(续) 订阅(主题)消息(消息持久化)
- Python3 socket
- Shiro集成Spring
- win10安装docker
- 史上最全最强SpringMVC详细示例实战教程
- windows下线程同步