assert和静态assert函数的使用

use of assert and static assert functions

本文关键字:assert 函数 静态      更新时间:2023-10-16

我正在努力了解static_assert和assert的用法以及它们之间的区别,但关于这个的来源/解释很少

这是一些代码

// ConsoleApplication3.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "conio.h"
#include "cassert"
#include "iostream"

int main()
{
assert(2+2==4);
std::cout << "Execution continues past the first assertn";
assert(2+2==5);
std::cout << "Execution continues past the second assertn";
_getch();
}

对冗余的评论将不胜感激(因为我正在学习"如何c++")

cmd中的输出

Execution continues past the first assert
Assertion failed: 2+2==5, file c:userscharlesdocumentsvisual studio 2012pro
jectsconsoleapplication3consoleapplication3consoleapplication3.cpp, line 14

我一直试图找出它的不同方法和用途,但据我所知,它是一种运行时检查和另一种"类型"的if语句

有人能澄清一下它们的用途,并解释一下每一种的作用和区别吗?

您可以将断言视为健全性检查。您知道某个条件应该为真,除非您搞砸了什么,所以断言通过。如果您确实搞砸了东西,断言将失败,并且您将被告知出了问题。它只是为了确保代码的有效性。

当条件是常量表达式时,可以使用static_assert。这基本上意味着编译器能够在程序实际运行之前评估断言。系统会提醒您,static_assert在编译时失败,而普通的assert只会在运行时失败。在您的示例中,您可以使用static_assert,因为表达式2+2==42+2==5都是常量表达式。

static_assert对于检查编译时结构(如模板参数)非常有用。例如,您可以断言给定的模板参数T必须是具有以下内容的POD类型:

static_assert(std::is_pod<T>::value, "T must be a POD type");

请注意,您通常只希望在调试期间检查运行时断言,因此可以通过#defineNDEBUG禁用assert

assert()是一个宏,其扩展取决于是否定义了宏NDEBUG。如果是这样的话,assert()不会扩展到任何东西——这是一个禁忌。当未定义NDEBUG时,assert(x)扩展为运行时检查,类似于以下内容:

if (!x) cause_runtime_to_abort()

通常在"发布"版本中定义NDEBUG,而在"调试"版本中不定义它。这样,assert()只在调试代码中执行,根本不会将其转换为发布代码。通常使用assert()来检查应该始终为true的东西,例如函数的前置条件和后置条件或类的不变量。失败的assert(x)应该意味着"程序员认为x成立,但代码中的某个错误(或他们的推理)使这一点不真实。">


static_assert()(在C++11中引入)是一个关键字,类似于typedef。它只能用于编译时表达式,如果失败,将导致编译错误。它不会产生任何目标代码,也根本不会被执行。

如果您想防止错误地实例化模板,static_assert()在模板中非常有用。例如:

template <class IntType>
IntType foo(IntType x)
{
static_assert(std::is_integral<IntType>::value, "foo() may be used with integral types only.");
// rest of the code
}

这样,尝试用例如float调用foo()将导致编译时错误,并产生合理的消息。

有时,static_assert()在模板之外也很有用,例如:

static_assert(sizeof(void*) > 4, "This code does not work in 32 bits");

static_assert在编译时求值,assert在运行时求值。

我怀疑你找不到任何来源,但我还是会给出一些解释。

assert用于永远不会失败的运行时检查。如果失败,程序将不体面地终止。您可以通过指定编译时标志来禁用发布版本的断言。由于断言永远不会失败(毕竟它们是断言),在一个工作程序中,这不应该有任何区别。但是,断言中的表达式不能有副作用,因为不能保证它们被执行。示例:

unsigned int add_non_negative_numbers(int a, int b)
{
// good
assert(a > 0);
assert(b > 0);
return (unsigned int)a + (unsigned int)b;
}
void checked_read(int fd, char *buffer, int count)
{
// BAD: if assertions are disabled, read() will _not_ be called
assert(read(fd, buffer, count) == count);
/* better: not perfect though, because read can always fail
int read_bytes = read(fd, buffer, count);
assert(read_bytes == count);
*/
} 

static_assert是新的,可用于执行编译时检查。当它们失败时会产生编译器错误,并阻止程序编译:

static_assert(sizeof(char) == 1, "Compiler violates the standard");