使用断言和静态断言函数

时间:2014-01-17 10:37:18

标签: c++ assert assertions static-assert

我试图理解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 assert\n";
    assert(2+2==5);
    std::cout << "Execution continues past the second assert\n";
    _getch();
}

对redundency的评论将受到赞赏(因为我正在学习“如何使用c ++”)

输出cmd

Execution continues past the first assert
Assertion failed: 2+2==5, file c:\users\charles\documents\visual studio 2012\pro
jects\consoleapplication3\consoleapplication3\consoleapplication3.cpp, line 14

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

有人可以澄清一下用法并解释每个人做了什么,他们有什么区别?

4 个答案:

答案 0 :(得分:3)

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

当条件是常量表达式时,可以使用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");

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

答案 1 :(得分:1)

在编译时评估static_assert,在运行时评估assert

答案 2 :(得分:1)

我怀疑你找不到任何这方面的资料,但我会给出一些解释。

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");

答案 3 :(得分:1)

assert()是一个宏,其扩展取决于是否定义了宏NDEBUG。如果是这样,assert()不会扩展到任何东西 - 这是一个无操作。如果未定义NDEBUGassert(x)将扩展为运行时检查,如下所示:

if (!x) cause_runtime_to_abort()

在“release”版本中定义NDEBUG并在“debug”版本中保留未定义是很常见的。这样,assert()仅在调试代码中执行,并且根本不会使其成为发布代码。您通常使用assert()来检查应该始终为真的事物 - 例如,函数的前置条件和后置条件或类的不变量。失败的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
}

这样,尝试用例如foo()拨打float将导致编译时错误,并显示合理的消息。

有时候,static_assert()也可以在模板之外使用,例如像这样:

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