【发布时间】:2011-10-26 12:59:39
【问题描述】:
在编写异常安全代码时,需要考虑所有调用函数的异常安全保证(none、basic、strong 或 no-throw)。由于编译器没有提供任何帮助,我认为函数命名约定在这里可能会有所帮助。是否有任何一种既定的符号标准来指示功能提供的异常安全保证水平?我在想一些类似匈牙利的东西:
void setFooB(Foo const& s); // B, offers basic guarantee
int computeSomethingS(); // S, offers strong guarantee
int getDataNT() throws(); // NT, offers no-throw
void allBetsAreOffN(); // N, offers no guarantee
编辑:我同意 cmets 认为这种命名约定很丑陋,所以请允许我详细说明我提出建议的原因。
假设我重构了一些代码,并在该过程中更改了函数提供的异常安全级别。如果保证已经从强到基本(也许通过提高速度来证明),那么每个调用重构函数的函数都必须重新考虑它们的异常安全性。如果保证的更改也触发了函数名称的更改,它将允许编译器帮助我至少标记更改函数的所有用途。这是我建议上述命名约定的理由,尽管它是有问题的。这与 const 非常相似,其中函数的 const 特性的变化会对其他调用函数产生级联影响,但在这种情况下,编译器会提供非常有效的帮助。
所以我想我的问题是,人们养成了什么样的工作习惯来确保代码真正满足他们预期的异常保证,尤其是在代码维护和重构期间。
【问题讨论】:
-
拜托,不需要另一个代码疣系统,我们还不够吗?
-
“异常安全代码”是什么意思?没有必要确保永远不会抛出任何函数,并且所有标准容器都可能习惯性地抛出......通常你会确定程序流中可以明智地处理异常并处理那些你可以处理的地方(重新抛出所有其他人),而不用担心每个人来自哪里 - 否则你只是回到 C 风格的错误处理......
-
不要那样做,就像 Gene 建议的那样。也许您可以将它们放在单独的名称空间中,用一些模板或默认参数支持它们。最好将它们放在单独的标题/命名空间中并妥善记录。
-
一切都应至少提供基本保证,因此您不必担心没有。记录(通过 cmets 或好的、有意义的名称)提供更强保证的事物;根据我的经验,这些并不常见。考虑使用
throws()或noexcept来明确保证不投掷(但也要研究throws()的缺点)。请不要为此目的使用可怕的名称装饰。 -
@Kerrek SB:异常保证不是关于停止异常,而是关于在抛出异常时您对对象的保证。大多数对象可能应该提供强有力的保证(如 STL 容器)(它可以工作或抛出异常而不改变对象),但有时您需要的只是基本保证(对象不会处于无效状态) .很少有方法需要不抛出保证(除了析构函数和 swap()),你应该足够聪明,永远不要编写不提供保证的代码。
标签: c++ exception hungarian-notation