由于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
?
答案 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
或等效编译),则不会进行检查,因此不会报告错误。通常的做法是在开发(内部,调试)版本中启用断言,并在发布版本中禁用断言。