c++ - with - 断言总是坏的吗?
static_assert (8)
关于断言,我唯一可以说的非常消极的是他们不会在零售代码中运行。 在我们的团队中,我们倾向于因此避免断言。 相反,我们使用契约,这是在零售和调试中运行的断言。
我们现在唯一一次使用断言是否满足以下条件之一。
- 断言代码具有显着的性能影响
- 特殊情况并非致命
- 偶尔会有一段代码可能会或可能不会消亡。 我们将添加一个断言,基本上说“你是怎么来到这里的”。 不解雇并不意味着代码确实已经死了但是如果QA给我发电子邮件并说“这个断言意味着什么”,我们现在有一个复制品来获取特定的代码(当然,它会立即记录)。
我曾经在一家公司工作,其中一些主要架构师/开发人员已经强制要求断言不使用的各种项目,并且他们通常会从代码中删除并替换为异常。
我觉得它们在编写正确的代码时非常重要。 任何人都可以建议如何证明这样的授权是合理的吗? 如果是这样,断言有什么问题?
否决assert()
一个原因是,可以编写在定义NDEBUG
时正常工作的代码,但在未定义NDEBUG
会失败。 或相反亦然。
这是一个好的程序员不应经常陷入困境的陷阱,但有时原因可能非常微妙。 例如, assert()
的代码可能会推动可执行文件中的内存分配或代码位置,使得可能发生的分段错误(反之亦然)。
根据团队的技能水平,将他们从风险区域引导是一个好主意。
它取决于系统的关键性 :断言是一种失败的策略 ,而系统可以执行某种恢复时可以使用异常。
例如,我不会在银行应用程序或电信系统中使用断言:我会抛出一个异常,它会在调用堆栈中占据上层。 在那里,可以清理资源,并且可以处理下一个呼叫/交易; 只有一个会丢失。
我们使用断言来记录假设 。
我们在代码审查中确保在断言中不执行任何应用程序逻辑,因此在发布之前不久就将它们关闭是非常安全的。
断言和异常用于两个不同的事情。
断言用于永远不会发生的状态。 例如,signalton指针永远不应为null,并且应该在开发期间使用assert拾取此错误。 处理它有一个例外是没有更多的工作。
另一方面,异常用于可能在应用程序的正常运行中发生的罕见状态。 例如,使用fopen并返回空指针。 它可能会发生,但大多数时候它会返回一个有效的指针。
使用断言是错误的也不是正确的,但它归结为个人偏好,因为在一天结束时它是一个使编程更容易并且可以被其他工具取代的工具。
断言是一件很棒的事情,但不要与参数/返回值检查混淆。 您在不相信会发生的情况下使用它们,而不是在您预期可能发生的情况下使用它们。
我最喜欢使用它们的地方是在真正不应该到达的代码块中 - 例如在switch
的default
情况 - 在enum上的陈述,其中包含每个可能的枚举值的case
。
你可以用新值扩展enum是相对常见的,但是不要更新涉及枚举的所有switch
-statements,你会想尽快知道。 在这种情况下,失败是最好的。
当然,在那些地方你通常也想要在生产版本中打破的东西。 但强烈建议在这种条件下abort()
的原则。 调试器中的良好堆栈跟踪为您提供了比猜测更快地修复错误的信息。
注意,在析构函数中抛出异常是未定义的行为。
调试版本中是否存在断言,但发布版本中是否存在?
如果要验证/断言某些内容,是否要在发布版本和调试版本中执行此操作?