什么是RAII?
RAII,英文全称是 Resource Acquisition Is Initialization,直译为资源获取即初始化,是 C++ 所特有的资源管理方式。
RAII 依托栈和析构函数,来对所有的资源——包括堆内存在内——进行管理。目前C++中智能指针就是RAII的典型代表。
RAII的理解
让我们先看一段代码:
#include
enum class AnimalType
{
tiger,
monkey,
duck,
};
class Animal
{
public:
Animal() = default;
virtual void printType()
{
std::cout << "Animal" << std::endl;
}
};
class Tiger : public Animal
{
public:
Tiger() = default;
void printType()
{
std::cout << "Tiger" << std::endl;
}
};
class Monkey : public Animal
{
public:
Monkey() = default;
void printType()
{
std::cout << "Monkey" << std::endl;
}
};
class Duck : public Animal
{
public:
Duck() = default;
void printType()
{
std::cout << "Duck" << std::endl;
}
};
Animal* createAnimal(AnimalType type)
{
switch (type)
{
case AnimalType::tiger:
return new Tiger();
case AnimalType::monkey:
return new Monkey();
case AnimalType::duck:
return new Duck();
default:
return new Animal();
}
}
int main()
{
Animal* a = createAnimal(AnimalType::tiger);
a->printType();
return 0;
}
上面的代码很简单,就是一个Animal父类,其他三个类继承了Animal。然后通过工厂的方式,去创建对应的实体类。但有个问题就是创建的对象很容易被忘记释放。这时候C++的RAII机制就派上用处了。在上述代码中新增如下代码:
class AnimalWrapper
{
public:
explicit AnimalWrapper(Animal* ptr = nullptr) : m_ptr(ptr)
{}
~AnimalWrapper()
{
delete m_ptr;
}
Animal* get() const
{
return m_ptr;
}
private:
Animal* m_ptr;
};
然后你可以用如下方式去创建对象:
AnimalWrapper animal = AnimalWrapper(createAnimal(AnimalType::tiger));
animal .get()->printType();
这里的animal是放在栈中的,当animal 消亡的时候,会调用AnimalWrapper类中的析构函数,从而释放了之前创建的对象。
总结
RAII其实就是依托栈数据的特性,在生命周期结束后,回去调用类的析构函数,然后你在析构函数中去维护内存的释放。当然对于关闭文件,释放同步锁以及释放其他重要的系统资源也是可行的。