为什么我不能使用 if 语句而不是在 C++ 中使用 assert?

Why can't I use an if statement instead of using assert in C++?

既然 assert 只是检查其参数中的语句是否成立,为什么我们不简单地使用 if 条件来检查呢?

Usage of assert

void print_number(int* somePtr) {
  assert (somePtr !=NULL);
  printf ("%d\n",*somePtr);
}

Usage of if

void print_number(int* somePtr) {
  if (somePtr != NULL)
       printf ("%d\n",*somePtr); 
}

任何人都可以指出两者之间的区别以及使用一个相对于另一个的优势吗?

还有,为什么这里大多数人更喜欢 assert 而不是 if

使用断言为您提供了一种在开发时验证值并在生产时忽略这些检查的简单方法。

转述 SO 文档过去所说的内容:

If an assertion fails and assertions are active, then the program stops with an error message (and often a core dump). If assertions are not active (the code is compiled with -DNDEBUG or equivalent), then the check is not made and therefore the error is not reported. A common practice is to leave assertions enabled in development (internal, debug) builds, and to disable assertions in release builds.

Can anybody point out the difference between the two

如果你看一下这个reference,你会发现如果定义了NDEBUG宏,assert的条件就不会被检查。此外,如果不满足条件,则将调用 std::abort

if 语句的条件始终被检查。如果不满足条件,则不会调用 std::abort - 除非那是 else 语句所做的。

and advantages of using one over the other?

assert的好处是可以用NDEBUG宏来控制是否检查条件。启用检查的好处是在开发时能够捕获错误。禁用检查的优点是避免在可能无法提供检查的发布版本中进行检查。

使用普通 if 语句的优点是,该错误也可以在发布版本中捕获。缺点是条件检查的运行成本。

断言不应该在正确的代码中触发。如果是这样,则您的代码中存在错误,需要修复。所以使用这样的函数:

void print_number(int* somePtr) {
  assert (somePtr!=NULL);
  printf ("%d\n",*somePtr);
}

你是说永远不应该将空指针传递给这个函数,如果是,那么传递它的代码是不正确的。

但是,您的功能在这里:

void print_number(int* somePtr) {
  if (somePtr != NULL)
       printf ("%d\n",*somePtr); 
}

你是说可以将一个空指针传递给这个函数,只是在那种情况下它什么都不做。

比较你的断言版本的更合适的函数是这样的:

void print_number(int* somePtr) {
  if (somePtr == NULL)
      std::abort();
  printf ("%d\n",*somePtr);
}

这与 assert 的作用基本相同(尽管没有有用的诊断消息)。这里的区别在于,如果定义了 NDEBUG,断言就会消失。此函数(带有 if, then abort)将在所有情况下进行检查。

assert 的要点是在速度无关紧要的开发过程中提供正确性测试,并在应用程序发布时删除这些检查。

assert 检查在定义 NDEBUG 宏时消失,因此没有它们程序 运行 运行速度更快。所以在开发期间 NDEBUG 是未定义的,但是当应用程序被编译发布时,NDEBUG 被定义。

GCC 中,您可以打开 assert 检查 开发 模式:

g++ -O0 -g3 -U NDEBUG ...

并在 release 模式下关闭它们:

g++ -O3 -g0 -D NDEBUG ...

一个普通的if语句总是运行无论是在开发中还是在发布代码中。因此 if() 对最终性能有影响,而 assert 则没有。此外,assert 将导致应用程序在失败时立即 终止 ,因此应在最终版本中将其关闭。