4

在编写异常安全代码时,需要考虑所有调用函数的异常安全保证(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

编辑:我同意这种命名约定丑陋的评论,所以请允许我详细说明我提出建议的原因。

假设我重构了一些代码,并在该过程中更改了函数提供的异常安全级别。如果保证已经从强到基本(也许通过提高速度来证明),那么每个调用重构函数的函数都必须重新考虑它们的异常安全性。如果保证的更改也触发了函数名称的更改,它将允许编译器帮助我至少标记更改函数的所有用途。这是我建议上述命名约定的理由,尽管它是有问题的。这与 const 非常相似,其中函数 const 的变化会对其他调用函数产生级联影响,但在这种情况下,编译器会提供非常有效的帮助。

所以我想我的问题是,人们养成了什么样的工作习惯,以确保代码真正满足他们预期的异常保证,尤其是在代码维护和重构期间。

4

4 回答 4

5

我通常发现自己在注释(doxygen)中记录了这一点,除了不抛出保证之外,当且仅当确定函数保证不抛出时,我经常用throw() 异常规范标记,并且异常安全很重要。

也就是说,我通常更担心部分代码中的异常,其中未处理的异常会导致问题,并在本地处理(确保您的代码通过其他方式是异常安全的,如 RAII,在外部执行工作然后合并没有抛出操作的结果——即没有抛出交换,这是我主动标记为的唯一函数throw()

其他人可能有其他经历,但我发现这足以满足我的日常工作。

于 2011-08-13T22:43:35.243 回答
3

我认为你不需要做任何特别的事情。

我真正记录的唯一内容是 no-throw,那是因为语言的语法允许它。

您的项目中不应有不提供任何保证的代码。所以这只留下强大/基本的文件。对于这些,我认为您不需要显式调用它,因为它实际上不是关于方法本身,而是关于整个类(对于这两个保证)。他们提供的保证实际上取决于使用情况。

我想我认为我对所有事情都提供了强有力的保证(但我没有),有时它太贵了,有时它只是不值得付出努力(如果事情要抛出,它们无论如何都会被摧毁)。

于 2011-08-14T00:33:23.400 回答
1

我理解你愿意做好,但我不确定这样的命名约定。

总的来说,我对语言强制执行的命名约定保持警惕:它们很容易成为最大的骗子。

If you truly need such things, my suggestion is to get your hands on a compiler (Clang for example) and add a new set of attributes. Do note that you'll need to edit your Standard Library provided headers, and all 3rd party headers you rely on, to annotate them so that you can get those guarantees from the ground up.

Then you can have the compiler check the annotations (won't be trivial either...), and then the annotations become useful, because they cannot lie.

于 2011-08-14T13:12:53.137 回答
1

I am thinking about adding

@par Exception Safety

Strong guarantee

to my javadocs where appropriate.

于 2018-12-07T14:36:42.993 回答