通常需要完成以下任务:更改某些内容的状态,执行操作,然后将状态更改回原始状态。例如,在Win32 GDI中,需要更改背景颜色,然后进行一些绘制,然后再更改颜色。
可以直接完成:
COLORREF oldColor = SetBkColor( deviceContext, newColor );
drawStuff( deviceContext );
SetBkColor( deviceContext, oldColor );
或通过括号类来构造函数中的向前更改和析构函数中的向后更改:
CBkColorSwitcher switcher( deviceContext, newColor );
drawStuff( deviceContext );
//once control reaches end of block the switcher is destroyed and the change is reverted
括号类的优点是显而易见的 - 如果在更改之间抛出异常,则更改将被正确恢复。有什么缺点?
答案 0 :(得分:12)
这实际上是一个众所周知且广泛使用的C ++习语,称为RAII。 Win32 API是C API,它们的实现模式不同。如果您使用C ++进行编程,最好使用RAII惯用法处理资源分配和释放,方法是在C API上编写精简包装器,或者更好地重用现有的,精心设计的C ++替换。 Java程序员可以将RAII视为 finally 子句的替代。
答案 1 :(得分:4)
一些缺点,你需要编写更多代码,最终创建更多对象。 你无法控制它的使用。使用它错误,你失去了好处。 e.g。
CBkColorSwitcher * switcher = new CBkColorSwitcher(......)
那就是说,我认为优点远大于缺点,而更喜欢括号类方法
答案 2 :(得分:2)
我认为这是一种最佳做法。我没有看到任何缺点(除了可读性之外?)
答案 3 :(得分:2)
我看到的缺点是(至少在你给出的例子中):
话虽如此,使用RAII是做到这一点的“正确”方法,其好处远大于缺点。
答案 4 :(得分:1)
一个缺点是你通常必须定义一个新的类,这往往会有点开销。
除此之外,它是(另一个)非常常见的RAII示例,并且通常是一种非常好的方法。
编辑:如果您没有编写类只有一个函数,那么可以使用shared_ptr
在退出时执行一个代码块范围。我认为它对于大多数应用来说可能有点太可爱了。
答案 5 :(得分:1)
我挑剔,但是: