C++里对RAII的理解

RAII:Resource Acquisition Is Initialization 资源获取即初始化时机。

原理:利用对象的生命周期来管理资源,对象离开作用域自动调用析构函数。

1.RAII特征

  • 在构造时初始化资源或托管资源
  • 析构时释放资源
  • 一般表达对象语义,不允许复制或者赋值
  • 提供若干访问资源的方法

代码示例

class RAII {
 public:
     // 通过构造函数托管资源 
     RAII(T * p)
     : _p(p) {}
     
     // 获取所托管的资源的原生的裸指针
     T * get() { return _p; }// 访问资源的方法 
     T* operator->() { return _p; }
     T & operator*() { return *_p; }
     
     // 重置要托管的指针  
     void reset(T * p) {
         if(_p) {
             delete _p;
             _p = p;
         }
     }~RAII() {
         if(_p) {
             delete _p;
         }
     }private:
     T * _p;
 };
  
 void test0() {
     //智能指针(对象)托管指针
     RAII<Point> pPoint(new Point(1, 2));
     pPoint->print();
     (*pPoint).print();
     //获取所托管的资源的原生的裸指针
     cout << "address:" << pPoint.get() << endl;
 } 
  
 int main(void) {
     test0();
     return 0;
 }

2.对象语义

值语义:可以进行复制控制。

对象语义:不能进行复制控制,两种实现方法

//1.将拷贝构造函数和赋值运算符函数设置为私有(C++11前)
private:
//表达对象语义,禁止复制
SafeFile(const SafeFile &);
SafeFile & operator=(const SafeFile&);
//2.将拷贝构造函数和赋值运算符函数使用 =delete(C++11标准)
SafeFile(const SafeFile &) = delete;
SafeFile & operator=(const SafeFile&) = delete;

代码示例

//对象语义SafeFile
 #include <stdio.h>
 #include <iostream>
 #include <string>
 #include <fstream>
 using std::cout;
 using std::endl;
 using std::string;
 using std::ifstream;class SafeFile {
 public:
     // 构造函数初始化资源
     SafeFile(const string & filename)
     : _fp(nullptr) 
     {
         _fp = fopen(filename.c_str(), "a+");
         if(!_fp) {
             cout << "file " << filename << "not found" << endl;
         }
     }SafeFile(FILE * fp)
     : _fp(fp)
     {}void write(const string & str) {
         fwrite(str.c_str(), 1, str.size(), _fp);
     }
     
     // 析构时释放资源
     ~SafeFile() {
         if(_fp) {
             fclose(_fp);
             cout << "fclose(_fp)" << endl;
         }
     }// 2、C++11标准
     // 将拷贝构造函数和赋值运算符函数从当前类中删除掉
     SafeFile(const SafeFile &) = delete;
     SafeFile & operator=(const SafeFile&) = delete;private:
     // 1、C++11标准之前
     // 将拷贝构造函数和赋值运算符函数设为私有
     // SafeFile(const SafeFile &);
     // SafeFile & operator=(const SafeFile&);
     
 private:
     FILE * _fp;
 };
  
 void test0() {
     // 通过对象来托管文件指针,不需要进行文件指针的回收
     // sf对象生命周期被销毁时,会自动调用其析构函数,在析构函数内完成资源回收
     SafeFile sf("test.txt");
     // 只需要负责对文件指针进行操作即可
     sf.write("this is a test line\n");
 ​
     FILE * fp = nullptr;
     SafeFile sf2(fp);
     //sf2 = sf;//error  调用赋值运算符函数
     //SafeFile sf3 = sf;//error 调用拷贝构造函数
 }void test1() {
     // C++的所有流对象都是不能进行复制的,表达对象语义(客观对象都是独一无二的)
     ifstream ifs("test.txt");
     ifstream ifs2 = ifs; //调用拷贝构造函数
 }
  
 int main(void) {
     test0();
     return 0;
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值