这里已经有了很棒的答案,尤其是 Simucal。我只想补充一点:
攻击性编程非常适合调试。根据我的经验,“早期失败,经常失败”可以被认为是为代码中的错误设置陷阱。当出现问题时——无论是内存泄漏、内存踩踏、意外 NULL 等——如果程序立即失败(以及相关的调试数据,如调用堆栈),通常更容易发现问题。
防御性编程非常适合生产环境。应用程序发布后,您可能不希望最终用户看到一个漂亮的小对话框,上面写着“foo() 处未处理的异常”。如果您的应用程序处于测试阶段并且您仍在收集调试信息,那可能会很棒,但如果您正在发布一个稳定的应用程序,您可能只是不想在某些事情确实失败的罕见情况下用神秘的输出打扰用户。
有时你可以同时拥有它。我经常按照以下几行编写 C 代码:
void foo(char* data) {
ASSERT(data);
if (!data) { return; }
// ... work with data
}
如果此代码是在测试环境中编译的,则 assert 语句会捕获错误条件。如果它是在生产环境中编译的,则断言会被预处理器删除,并且 foo() 会静默失败。
异常比断言更具表现力和灵活性,并且有多种方法可以管理它们,以便应用程序在测试环境中及早失败,并在生产环境中记录错误时继续前进。根据项目的类型,这种设计可能对您有意义。