C++必知必会:RAII惯用法

文章目录

  • 使用RAII惯用法
  • 分配堆内存示例
  • 对多线程锁的获取和释放
  • 小结

使用RAII惯用法

RAII(Resource Acquisition Is Initialization, 资源获取即初始化)指资源在我们拿到的时候就已经初始化,一旦不需要该资源,就可以自动释放该资源。

对于C++来说,资源在构造函数中初始化(可以在构造函数中调用单独的初始化函数),在析构函数中释放或清理。常见的情形就是再函数调用过程中创建C++对象时分配资源,在C++对象出了作用域时将其自动清理和释放。

分配堆内存示例

如下代码,heapObj出了作用域该程序就会自动调用析构函数释放堆内存

// 定义HeapObjectWrapper RAII 对象
class HeapObjectWrapper
{
public:
	HeapObjectWrapper(int size)
	{
		m_p = new char[size];
	}

	~HeapObjectWrapper()
	{
		delete[] m_p;
		m_p = NULL;
	}

private:
	char* m_p;
};

// 使用 HeapObjectWrapper RAII对象
int main(void)
{
	HeapObjectWrapper heapObj(1024);
	if (测试操作) {}

	return 0;
}

对多线程锁的获取和释放

在日常写的代码里,为了避免死锁,通常会在每个可能退出的分支上都释放锁,随着逻辑越来越复杂,可能会在某个可能退出的分支上忘记释放锁。

RAII可以解决这个问题:将锁包裹成一个对象,在构造函数中获取锁,在析构函数中释放锁。

伪代码示例:

class SomeLockGuard
{
public:
	SomelockGuard()
	{
		// 加锁
		m_lock.lock();
	}

	~SomeLockGuard()
	{
		// 解锁
		m_lock.unlock();
	}
private:
	SomeLock m_lock;
};

int main(void)
{
	SomeLockGuard lockWrapper;
	if (条件1)
	{
		if (条件2) {
			//操作1
			return;
		}
		else {
			// 操作2
			return;
		}
	}

	if (条件3)
	{
		// 操作3
		return;
	}
}

使用RAII惯用法之后,我们就再也不必在每个函数出口处都加上释放锁的代码了,因为在函数调用结束后会自动释放锁。

小结

资源泄漏和死锁等问题具有非常强的隐蔽性,如果在生产环境中出现这些问题,则难以复现,排查和定位问题。
只要理解并熟练使用RAII惯用法不仅能让我们的代码更加简洁和模块化,也能让我们在开发阶段避免一部分资源泄漏和死锁问题。

你可能感兴趣的:(#,C++服务器开发,c++,开发语言)