文章目录
- 前言
- assert
- static_assert
前言
断言(Assertion)是一种常用的编程手段,用于排除程序中不应该出现的逻辑错误。它是一种很好的Debug工具。其作用是判断表达式是否为真。C++提供了assert
和static_assert
来进行断言。在C库中也有断言,其中断言与C++的相同,静态断言是_Static_assert
。
assert
assert
是一个仿函数宏,用于程序在运行时进行断言。它在标头<assert.h>中定义:
#ifdef NDEBUG
#define assert(condition) ((void)0)
#else
#define assert(condition)
#endif
若编译为release版本,编译器一般会定义NDEBUG,则assert失效。若是在debug下,assert 中的表达式若为假,则 assert 在标准错误输出上输出实现指定的诊断信息,并调用 std::abort 。
因为 assert 是仿函数宏,在 condition 中未被括号保护的逗号都被转译成宏参数的分隔符。而assert只接受一个参数,所以需要注意:
assert(std::is_same_v<int, int>); // 错误: assert 不接收二个参数
assert((std::is_same_v<int, int>)); // 正确:一个参数
static_assert(std::is_same_v<int, int>); // 正确:非宏
std::complex<double> c;
assert(c == std::complex<double>{0, 0}); // 错误
assert((c == std::complex<double>{0, 0})); // 正确
下面我们以一个字符串换成类作为示例代码,在设置内容和打印内容的时候进行断言,保证m_str分配了内存:
#include <assert.h>
#include <string.h>
#include <iostream>
using namespace std;
class StrBuf{
private:
char* m_str = nullptr;
public:
void alloc_memory(int size){
if(m_str == nullptr)
m_str = new char[size];
}
void setbuf(const char* str){
assert(m_str != nullptr);
strcpy(m_str,str);
}
void print(){
assert(m_str != nullptr);
for(int i=0;m_str[i]!='\0';i++)
cout<<m_str[i];
}
};
int main(){
StrBuf sbuf;
sbuf.alloc_memory(10);
sbuf.setbuf("hello");
sbuf.print();
}
输出正常,输出文本内容:
hello
如果我们将alloc_memory
函数(分配内存)注释掉:
int main(){
StrBuf sbuf;
//sbuf.alloc_memory(10);
sbuf.setbuf("hello");
sbuf.print();
}
输出的内容如下,运行时输出了断言结果,并结束了程序:
Assertion failed: m_str != nullptr, file D:\SingleSources\CPP\8.cpp, line 15
static_assert
C++11新增了静态断言static_assert
,它是内置的,因此使用静态断言不需要包含头文件。与assert在运行时检查不同,static_assert在编译阶段时检查源代码。
static_assert ( boolean expression, message ) //since C++11
static_assert ( boolean expression ) //since C++17
示例,静态断言一个为FALSE的表达式:
constexpr bool getFalseExpr(){
return false;
}
int main(){
static_assert(getFalseExpr(),"false expression");
}
编译时报错,并输出了信息"false expression":
8.cpp: In function 'int main()':
8.cpp:6:31: error: static assertion failed: false expression
6 | static_assert(getFalseExpr(),"false expression");
| ~~~~~~~~~~~~^~