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

时间:2016-08-14 21:12:07

标签: c++ if-statement exception-handling assert

由于assert只是检查其参数中的语句是否成立,为什么我们不使用if条件来检查?

  

断言的用法

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

使用if

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

有人可以指出两者之间的区别以及使用其中一个的好处吗?

另外,为什么大多数人更喜欢assert而不是if

4 个答案:

答案 0 :(得分:4)

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

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,然后中止)将在所有情况下进行检查。

答案 1 :(得分:1)

  

任何人都可以指出两者之间的区别

如果您查看此reference,则会发现如果定义了assert宏,则不会检查NDEBUG的条件。此外,如果条件不满足,则会调用std::abort

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

  

使用一个优于另一个的优势?

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

使用普通if语句的好处是,bug也可以在发布版本中捕获。缺点是条件检查的运行时成本。

答案 2 :(得分:1)

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

assert检查在定义NDEBUG宏时消失,因此没有它们,程序运行得更快。因此,在开发期间NDEBUG未定义,但在编译应用程序以进行发布时,NDEBUG已定义。

GCC中,您可以对开发模式进行assert检查:

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

关闭发布模式:

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

正常的if语句将始终运行,无论是开发还是发布代码。因此,当if()没有时,assert会对最终效果产生影响。此外,assert会导致应用程序在失败时立即终止,因此应在最终版本中将其关闭。

答案 3 :(得分:0)

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

解释SO文档曾经说过的内容:

  

如果断言失败且断言处于活动状态,则程序将停止并显示错误消息(通常是核心转储)。如果断言未激活(代码使用-DNDEBUG或等效编译),则不会进行检查,因此不会报告错误。通常的做法是在开发(内部,调试)版本中启用断言,并在发布版本中禁用断言。