assert和static_assert有什么区别?

时间:2013-08-13 13:20:24

标签: c++ assert

我知道static_assert在编译时发出断言,assert - 在运行时,但实践中的区别是什么?据我了解,内心深处它们是代码片段,如

if (condition == false) exit();
  • 有人可以举例说明 static_assert的工作原理,或仅 assert
  • 他们做了一个简单的if声明不能做的事吗?
  • 使用它们是不好的做法吗?

5 个答案:

答案 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));