assert和static_assert之间有什么区别

What is the difference between assert and static_assert?

本文关键字:assert 什么 区别 static 之间      更新时间:2023-10-16

我知道static_assert在编译时断言,assert-在运行时断言,但在实践中有什么区别?据我所知,在内心深处,它们是代码片段,就像

if (condition == false) exit();
  • 有人能给我举个例子,说明只有static_assert在哪里工作,或者只有assert在哪里工作
  • 他们做了简单的if语句做不到的事情吗
  • 使用它们是不好的做法吗

你问了三个问题,所以我会尽力回答每个问题。

  • 有人能给我举一个例子,说明只有static_assert在哪里工作,或者只有assert在哪里工作

static_assert适合在编译时测试代码中的逻辑。assert非常适合在运行时检查您期望总是有一个结果的案例,但在意外的情况下可能会以某种方式产生意外的结果。例如,您应该只使用assert来确定传递到方法中的指针是否为null,而这似乎永远不会发生。static_assert不会明白这一点。

  • 他们做了简单的if语句做不到的事情吗

assert可以用来中断程序执行,因此您可以使用if,一个适当的错误消息,然后停止程序执行以获得类似的效果,但assert在这种情况下要简单一些。static_assert当然只对编译问题检测有效,而if必须在编程上有效,并且不能在编译时评估相同的期望值。(然而,if可以用于在运行时吐出错误消息。)

  • 使用它们是不好的做法吗

一点也不!

static_assert旨在通过指定的消息使编译失败,而传统的assert旨在结束程序的执行。

好的,我会咬:

  • 如果您希望在违反静态条件时编译失败,则只有static_assert有效:static_assert(sizeof(void*) != 3, "Wrong machine word size");*只有动态断言才能捕获动态条件:assert(argc == 1);

  • 简单的if语句必须有效且可编译;静态断言会导致编译失败。

  • 没有。

*)一个实际的例子可能是防止滥用通用模板构造,例如int x; std::move<int&&>(x)

使用它们是不好的做法吗?

如果被滥用,是的,特别是assert

一种滥用是依赖于那些assert语句来发挥作用。您永远不应该依赖assert来做任何事情,因为可以在定义了NDEBUG的情况下编译代码,然后assert什么都不做。生产代码通常使用定义的NDEBUG进行编译,以确保这些assert语句消失。

除非你正在编写一个一次性的程序,它的使用时间不会超过一两天,否则你不应该使用来验证用户输入。用户不在乎代码在哪里失败,而且打印出来的消息对许多用户来说就像外语。它不会告诉用户如何修复错误。从设计上来说,这也是非常无情的。响应用户输入错误而发出的消息应该是告诉用户如何解决问题的消息。消息之后的最佳操作是为用户提供一种修复错误的方法。如果不能做到这一点,并且唯一可行的响应是结束程序,那么程序应该干净地终止。根据设计,assert不会导致干净停机。它调用abort()而不是exit()

abort()在许多机器上的一个结果是产生堆芯转储。对于程序员来说,核心转储是一个很好的错误消息。有了核心转储,程序员可以使用调试器详细查看出了什么问题。abort()的一个缺点是没有清理干净。Abort"终止程序,不执行自动或静态存储持续时间对象的析构函数,也不调用传递给atexit()的函数。"

一句话:使用assert测试编程错误是可以的(也是很好的),但只能在非生产环境中使用。使用其他方法来测试用户错误。

static_assert是一个编译器指令。它允许您在编译时检查类型信息。它将导致编译失败,并产生一条错误消息,在大多数IDE中,该消息都会被捕获并显示在IDE的错误窗口中。

static_assert(sizeof(int) == 4,"int should be 4 bytes");

assert用于运行时,您可以检查变量的值。如果断言失败,那么断言将被触发。这将导致一个错误消息框,该框将在某些操作系统的运行时出现(取决于断言实现)

assert(("mypointer  should never be null!", mypointer != nullptr));

应该提到的是,尽早发现bug非常重要。程序员想知道什么时候第一次出问题,而不是原来的问题引起的数百个问题。如果代码计算了一个错误的值,然后在随后的计算中使用它,那么所有这些计算都是错误的。找到问题的早期原因可以防止程序员不得不及时追踪错误。

运行时和编译都是如此。Assert在运行时可以帮助实现这一点,static_Assert在编译时可以帮助完成这一点。static_assert在编译时检查中非常有用,以确保某个头的版本可能与代码其余部分所需或测试的版本相同。如果static_assert告诉您更改了头版本,那么它比试图弄清楚为什么更改的头会触发所有这些编译错误要有用得多。它在编译过程中尽早检测到问题。

static_assert的另一个用途是检查编译是否使用了正确的编译器开关。例如,微软的编译器使用/J来表示char是无符号的8位值,而不是有符号的。如果代码需要,可以在编译时对其进行检查。