我知道static_assert
在编译时发出断言,assert
- 在运行时,但实践中的区别是什么?据我了解,内心深处它们是代码片段,如
if (condition == false) exit();
static_assert
的工作原理,或仅 assert
?if
声明不能做的事吗?答案 0 :(得分:49)
你问三个问题,所以我会尝试回答每一个问题。
static_assert
的工作原理,或仅 assert
? static_assert
适用于在编译时测试代码中的逻辑。 assert
适用于在运行期间检查一个你期望应该总是有一个结果的案例,但可能会在意外情况下以某种方式产生意外结果。例如,您应该仅使用assert
来确定传入方法的指针是否为null
,而这似乎永远不会发生。 static_assert
无法理解。
if
声明不能做的事吗? assert
可用于中断程序执行,因此您可以使用if
,相应的错误消息,然后暂停程序执行以获得类似的效果,但assert
是对于那种情况来说有点简单。 static_assert
当然仅对编译问题检测有效,而if
必须在编程时有效,并且无法在编译时评估相同的期望。 (但if
可用于在运行时发出错误消息。)
完全没有!
答案 1 :(得分:17)
static_assert
旨在使编译失败并显示指定的消息,而传统的assert
旨在结束程序的执行。
答案 2 :(得分:7)
好的,我会咬人:
如果您希望在违反静态条件时编译停止失败,则只有static_assert
有效:static_assert(sizeof(void*) != 3, "Wrong machine word size");
*只有动态断言才能捕获动态条件:assert(argc == 1);
简单if
语句必须有效且可编译;静态断言导致编译失败。
没有
*)一个实际的例子可能是防止滥用通用模板结构,例如int x; std::move<int&&>(x)
。
答案 3 :(得分:3)
使用它们是不好的做法吗?
如果被滥用,是的,特别是assert
。
一次滥用取决于要激活的assert
个语句。您永远不应该依赖assert
来执行任何操作,因为可以使用NDEBUG
定义编译代码,然后assert
不执行任何操作。生产代码通常使用NDEBUG
进行编译,以确保这些assert
语句消失。
除非您编写的一次性程序不会超过一天或两天,否则不应使用验证用户输入。用户不关心代码失败的位置,并且打印的消息看起来像许多用户的外语。它不会告诉用户如何修复错误。根据设计,这也是非常无情的。响应用户输入错误而发出的消息应该是一条消息,告诉用户如何解决问题。消息之后的最佳操作是为用户提供修复错误的方法。如果无法做到这一点,并且如果唯一可行的响应是结束程序,程序应该干净地终止。按照设计,assert
不会导致干净关闭。它会调用abort()
而不是exit()
。
abort()
在许多机器上的一个后果是产生核心转储。对于程序员来说,核心转储是一个很好的错误消息。通过核心转储,程序员可以使用调试器来详细查看出错的地方。 abort()
的缺点是事情没有被清理干净。 Abort“终止程序而不对自动或静态存储持续时间的对象执行析构函数,而不调用传递给atexit()
的函数。”
结论:使用assert
测试编程错误是可以的(并且很好),但仅限于非生产设置。使用其他东西来测试用户错误。
答案 4 :(得分:1)
static_assert
是一个编译器指令。它允许您在编译时检查类型信息。它将导致编译失败并产生一条错误消息,在大多数IDE中都会被捕获并显示在IDE的错误窗口中。
static_assert(sizeof(int) == 4,"int should be 4 bytes");
assert
用于运行时,您可以检查变量的值。如果断言失败,那么断言将触发。这将导致在某些操作系统中出现在运行时的错误消息框(断言依赖于实现)
assert(("mypointer should never be null!", mypointer != nullptr));