Fab*_*orr 83 c++ assert coding-style
我倾向于在我的C++代码中添加许多断言,以便在不影响发布版本性能的情况下简化调试.现在,assert
是一个纯C宏设计,没有考虑到C++机制.
另一方面std::logic_error
,C++定义了在程序逻辑中存在错误(因此名称)的情况下抛出的内容.抛出一个实例可能只是一个完美的,更多的C++替代品assert
.
问题是,assert
并且abort
两者都立即终止程序而不调用析构函数,因此跳过清理,而手动抛出异常会增加不必要的运行时成本.解决这个问题的一种方法是创建一个自己的断言宏SAFE_ASSERT
,它就像C对应物一样工作,但在失败时抛出异常.
我可以想到关于这个问题的三种看法:
#define
在C++中使用s同样糟糕.NDEBUG
这种情况在发布版本中永远不会发生.捕获是不必要的,并公开内部代码的实现细节main()
.这个问题有明确的答案吗?有专业的参考吗?
编辑:跳过析构函数当然没有未定义的行为.
Ker*_* SB 91
断言用于调试.您提供的代码的用户永远不应该看到它们.如果一个断言命中,你的代码需要修复.
例外情况适用于特殊情况.如果遇到一个,用户将无法做她想做的事,但可能能够在其他地方恢复.
错误处理是针对正常的程序流程.例如,如果您提示用户输入数字并获得不可分类的内容,这是正常的,因为用户输入不在您的控制之下,您必须始终处理所有可能的情况.(例如循环,直到你有一个有效的输入,说"对不起,再试一次".)
bam*_*s53 67
断言完全适用于C++代码.异常和其他错误处理机制并不真正与断言相同.
错误处理是指有可能很好地恢复或向用户报告错误.例如,如果尝试读取输入文件时出错,您可能想要对此进行一些操作.错误可能是由错误引起的,但它们也可能只是给定输入的适当输出.
断言用于检查在通常不检查API时是否满足API的要求,或用于检查开发人员认为通过构造保证的事情.例如,如果一个算法需要排序的输入,你通常不会检查它,但你可能有一个断言来检查它,以便debug build标记那种bug.断言应始终指示错误操作的程序.
如果您正在编写一个程序,其中不正常的关闭可能会导致问题,那么您可能希望避免断言.严格按照C++语言定义的未定义行为在这里不符合这样的问题,因为命中断言可能已经是未定义行为的结果,或者违反了其他一些可能阻止某些清理工作正常的要求.
此外,如果您根据异常实现断言,那么它可能会被捕获并"处理",即使这与断言的目的相矛盾.
Jon*_*ely 12
由于alling abort()没有运行析构函数不是未定义的行为!
如果是,那么调用std::terminate()
也是未定义的行为,那么提供它的重点是什么?
assert()
在C++中和在C中一样有用.断言不是用于错误处理,而是用于立即中止程序.
nog*_*ard 12
断言可用于验证内部实现不变量,例如在执行某些方法之前或之后的内部状态等.如果断言失败,则实际上意味着程序的逻辑被破坏而您无法从中恢复.在这种情况下,您可以做的最好是尽快中断而不向用户传递异常.断言(至少在Linux上)的真正好处是核心转储是由于进程终止而生成的,因此您可以轻松地调查堆栈跟踪和变量.这比理解异常消息更有助于理解逻辑失败.
恕我直言,断言是为了检查条件,如果被违反,其他一切都是废话。因此,您无法从它们中恢复,或者更确切地说,恢复是无关紧要的。
我将它们分为两类:
浮动概率(){返回-1.0;}
断言(概率()> = 0.0)
整数 x = 1;
断言(x > 0);
这些都是微不足道的例子,但与现实相差不远。例如,考虑返回负索引以用于向量的朴素算法。或定制硬件中的嵌入式程序。或者更确切地说,因为sh*t 发生了。
如果存在此类开发错误,您不应该对实施的任何恢复或错误处理机制充满信心。这同样适用于硬件错误。