assert和static_assert之间有什么区别
What is the difference between assert and static_assert?
我知道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位值,而不是有符号的。如果代码需要,可以在编译时对其进行检查。
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 警告处理为错误这里有什么问题
- 什么时候调用组成单元对象的析构函数
- #定义c-预处理器常量..我做错了什么
- 努力将整数转换为链表。不知道我在这里做错了什么
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 什么时候在C++中返回常量引用是个好主意
- 当在同一名称空间中有两个具有相同签名的函数时,会发生什么
- C++避免重复声明的语法是什么
- c++库的公共头文件中应该包含什么
- 问题:什么是QAbstractItemView::NoEditTriggers的反面
- 有什么方法可以遍历结构吗
- 当类在C++中定义时,有什么方法可以"register"类吗?
- ifstream什么都没读
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 能够使用debug.assert()函数需要什么
- std::assert发生了什么
- P::************** 在 Boost assert.hpp 文件中是什么意思
- assert和static_assert之间有什么区别
- assert.h在cpp中有什么用?