我正在阅读谷歌C++风格指南,并在例外部分感到困惑.根据指南,使用它的一个缺点是:
异常安全需要RAII和不同的编码实践.需要大量的支持机制才能使编写正确的异常安全代码变得容易.此外,为了避免要求读者理解整个调用图,异常安全代码必须将写入持久状态的逻辑隔离到"提交"阶段.这将带来好处和成本(可能是您被迫混淆代码以隔离提交的地方).允许例外将迫使我们总是支付这些费用,即使它们不值得
具体来说,我不明白的陈述是这样的:
(...)异常安全代码必须将写入持久状态的逻辑隔离到"提交"阶段.
还有这个:
(...)也许你被迫混淆代码来隔离提交(...).
我想我不习惯术语"持久状态","提交阶段","混淆代码以隔离提交".关于这些术语的一些小解释,例子或参考可能是很好的,也可能是为什么这是真的.
GMa*_*ckG 36
基本上,现代C++使用范围限制资源管理(SBRM或RAII).也就是说,一个对象清理其析构函数中的资源,该资源可以保证被调用.
除非您的代码不是现代的,否则这一切都很好.例如:
int *i = new int();
do_something(i);
delete i;
Run Code Online (Sandbox Code Playgroud)
如果do_something抛出异常,你就泄露了.正确的解决方案是不要像这样在野外放置资源,即:
std::auto_ptr<int> i(new int());
do_something(i.get());
Run Code Online (Sandbox Code Playgroud)
现在它永远不会泄漏(代码更清洁!).
我认为指南试图说的是我们已经拥有了所有这些旧代码,使用现代风格需要花费太多精力.所以我们不要使用例外.(而不是修复所有代码......我非常不喜欢Google Style Guide.)
"写入持久状态" 大致意味着" 写入文件 "或" 写入数据库 ".
"进入'提交'阶段." 大致意思是"一次完成所有写作"
"也许你被迫混淆代码以隔离提交"意味着" 这可能会使代码难以阅读 "(轻微滥用"混淆"一词意味着故意使某些东西难以阅读,而在这里它们意味着无意中使它难以阅读,但滥用可能是故意的,因为戏剧性的影响)
详细阐述:"写入持久状态"更接近意味着"向某些永久性媒体写出有关此对象的所有细节,以便重新创建它".如果写入被异常中断,则那些"写出的细节"(即"持久状态")可能包含新状态的一半和旧状态的一半,从而在重新创建时导致无效对象.因此,写国家必须作为一个不间断的行为.
关于持久状态的说法是这样的:即使你正在使用RAII并且你的对象被正确破坏,允许你清理,如果try块中的代码以某种方式修改了系统的状态,你很可能需要找出如何回滚这些更改,因为操作未成功完成.他们在这里使用术语"提交",因为它与事务有关,这一概念是,当您执行操作时,系统的状态应该好像是100%成功完成或根本没有发生.
以下是即使使用RAII,这也会变得混乱:
struct MyClass
{
MyClass(Foo* foo)
{
m_bar = new Bar;
foo->changeSomeState();
}
~MyClass()
{
delete m_bar;
}
Bar* m_bar;
};
Run Code Online (Sandbox Code Playgroud)
现在,如果你有这个代码:
try
{
MyClass myClass(foo);
Baz baz;
baz.doSomething(); // Throws an exception
}
catch(...)
{
// MyClass doesn't leak memory, but should it try to undo
// the change it made to foo?
}
Run Code Online (Sandbox Code Playgroud)
因此,为了正确处理这种情况,您必须添加更多代码以将其视为事务,并在抛出异常时回滚对try块中的持久状态所做的任何更改.他们只是说强制事务语义会使代码混乱(混淆).
我不同意禁止例外,顺便说一下,只是试图表明他们所指的问题.
| 归档时间: |
|
| 查看次数: |
6479 次 |
| 最近记录: |