一 什么是 RAII ?
RAII (Resource Acquisition Is Initialization)是由c++之父Bjarne Stroustrup提出的,中文翻译为资源获取即初始化, 其含义是:用局部对象来管理资源的技术,这里所说的资源指的是操作系统中的内存资源、网络套接字等等;局部对象指的是定义在栈上的对象,其生命周期的管理是由操作系统完成的。
二 为什么引入 RAII ?
计算机操作系统的资源使用一般分为三个步骤
- 申请资源
- 使用资源
- 释放资源
然而在实际中,程序员常常会忘记最后一步:释放资源。
所以程序界就想如何在程序员中让资源自动销毁呢?c++之父给出了解决问题的方案:RAII,它充分的利用了C++语言局部对象自动销毁的特性来控制资源的生命周期
三 使用示例
1. 例子一
// person.h
#include<string>
class Person
{
public:
Person(std::string name);
~Person();
private:
std::string m_name;
};
//------------------------
// person.cpp
#include "person.h"
#include<iostream>
Person::Person(std::string name):m_name(name)
{
std::cout << "Person constructor name: " << m_name << std::endl;
}
Person::~Person()
{
std::cout << "Person destructor name: " << m_name << std::endl;
}
// -----------------------
// main.cpp
#include "person.h"
void func()
{
Person p1("per1 ---");
Person p2("per2 ---");
Person p3("per3 ---");}
int main(int argc, char *argv[])
{
func();
return 0;
}
输出结果:
2. 例子2
1. 代码:
// animalbase.h
class AnimalBase
{
public:
AnimalBase();
virtual~AnimalBase();
};
// ----------------------------
// animalbase.cpp
#include<iostream>
#include<string>
#include"animal.h"
AnimalBase::AnimalBase()
{
std::cout << "Animal constructor --- " << std::endl;
}
AnimalBase::~AnimalBase()
{
std::cout << "Animal destructor --- " << std::endl;
}
// ----------------------------
// elephant.h
#include "animal.h"
class Elephant: public AnimalBase
{
public:
Elephant();
~Elephant();
};
// ----------------------------
// elephant.cpp
#include "elephant.h"
#include<iostream>
Elephant::Elephant()
{
std::cout << "Elephant constructor --- " << std::endl;
}
Elephant::~Elephant()
{
std::cout << "Elephant destructor --- " << std::endl;
}
// ----------------------------
// lion.h
#include"animal.h"
class Lion : public AnimalBase
{
public:
Lion();
~Lion();
};
// ----------------------------
// lion.cpp
#include "lion.h"
#include<iostream>
Lion::Lion()
{
std::cout << "Lion constructor --- " << std::endl;
}
Lion::~Lion()
{
std::cout << "Lion destructor --- " << std::endl;
}
// ----------------------------
// tiger.h
#include"animal.h"
class Tiger : public AnimalBase
{
public:
Tiger();
~Tiger();
};
// ----------------------------
// tiger.cpp
#include "tiger.h"
#include<iostream>
Tiger::Tiger()
{
std::cout << "tiger constructor --- " << std::endl;
}
Tiger::~Tiger()
{
std::cout << "tiger destructor --- " << std::endl;
}
// ----------------------------
// animalmanager.h
class AnimalBase;
class AnimalManager
{
public:
AnimalManager(AnimalBase* animal_ptr);
~AnimalManager();
private:
AnimalBase* m_animal_ptr;
};
// ----------------------------
// animalmanager.cpp
#include "animalmanager.h"
#include"animal.h"
AnimalManager::AnimalManager(AnimalBase* animal_ptr):m_animal_ptr(animal_ptr)
{
}
AnimalManager::~AnimalManager()
{
if(m_animal_ptr)
delete m_animal_ptr;
}
// ----------------------------
// main.cpp
#include"animal.h"
#include"animalmanager.h"
#include"lion.h"
#include"tiger.h"
#include"elephant.h"
void testFunc()
{
AnimalManager manger1(new Lion);
AnimalManager manger2(new Elephant);
AnimalManager manger3(new Tiger);
}
int main(int argc, char *argv[])
{
testFunc();
return 0;
}
输出结果:
注意:
这里我们发现,析构函数是按照构造的顺序反着来的,这里的原理在于 c++ 中 函数压入栈的顺序,最后压入栈的是 per3 ,因而 per3 也是最先弹出栈的,所以 per3 也是最先析构的。
关于 c++ 函数压入栈的顺序,后面再讲。