【C++grammar】断言与表达式常量
目录
- 1、常量表达式和constexpr关键字
- 2、断言与C++11的静态断言
- 1.1. assert : C语言的宏(Macro),运行时检测。
- 1.2. assert()依赖于NDEBUG 宏
- 1.3. assert 帮助调试解决逻辑bug (部分替代“断点/单步调试”)
- 2.1static_assert (C++11的静态断言 )
- 2.2. 作用:编译时断言检查
- 2.3. static_assert的用途
- 3. 1When to use assertions (何时使用断言)
- 3、声明与定义
- 1. What is "Declare/Declaration" (什么是声明)
- 2. What is "define/definition" (什么是定义)
- 3. Differences between a declaration and a definition (定义与声明的区别)
1、常量表达式和constexpr关键字
常量表达式是编译期间就能计算其结果的表达式。
const修饰的对象既可能是编译期常量,也可能是运行期常量。
constexpr说明符声明可在编译时计算函数或变量的值
constexpr int max(int a , int b) { // c++11 引入 constexprif (a > b) return a; // c++14才允许constexpr函数中有分支循环等else return b;
}
int main() {int m = 1;const int rcm = m++; // rcm是运行期常量const int cm = 4; // 编译期常量,等价于: constexpr int cm = 4;int a1[ max(m , rcm)]; // 错误:m & rcm 不是编译期常量std::array<char , max(cm , 5)> a2; // OK: cm 和 5 是编译期常量
}
const用来告知程序员const指向的内容不可被修改,主要目的是为了避免写出bug。
constexpr在所有编译期常量的地方做限定。使得constexpr修饰的语句在编译期即可计算得到值。让编译期优化代码性能。
constexpr修饰的函数,要满足什么条件才能成为编译期常量表达式?
constexpr 函数的返回值必须在编译时就能被确定。
2、断言与C++11的静态断言
断言是一条检测假设成立与否的语句。
断言assert是一个宏,而非一个函数。
static_assert 是一个关键字,而非一个函数。
1.1. assert : C语言的宏(Macro),运行时检测。
用法:包含头文件 以调试模式编译程序
//assert( bool_expr ); // bool_expr 为假则中断程序
std::array a{ 1, 2, 3 }; //C++17 类型参数推导
for (size_t i = 0; i <= a.size(); i++) {assert(i < 3); //断言:i必须小于3,否则失败std::cout << a[ i ];std::cout << (i == a.size() ? "" : " ");
1.2. assert()依赖于NDEBUG 宏
NDEBUG这个宏是C/C++标准规定的,所有编译器都有对它的支持。
(1) 调试(Debug)模式编译时,编译器不会定义NDEBUG,所以assert()宏起作用。
(2) 发行(Release)模式编译时,编译器自动定义宏NDEBUG,使assert不起作用
如果要强制使得assert()生效或者使得assert()不生效,只要手动 #define NDEBUG 或者 #undef NDEBUG即可。
1.3. assert 帮助调试解决逻辑bug (部分替代“断点/单步调试”)
#undef NDEBUG // 强制以debug模式使用<cassert>
int main() {int i;std::cout << "Enter an int: ";std::cin >> i;assert((i > 0) && "i must be positive"); return 0;
}
上面示例的第6行代码中,若assert中断了程序则表明程序出bug了!程序员要重编代码解决这个bug,而不是把assert()放在那里当成正常程序的一部分
assert断言中所用的表达式可以不是是编译期常量表达式。
2.1static_assert (C++11的静态断言 )
2.1. static_assert ( bool_constexpr, message)
其中两个参数解释如下:
(1) bool_constexpr: 编译期常量表达式,可转换为bool 类型
(2) message: 字符串字面量 ,是断言失败时显示的警告信息。自C++17起,message是可选的
2.2. 作用:编译时断言检查
// 下面的语句能够确保该程序在32位的平台上编译进行。
// 如果该程序在64位平台上编译,就会报错 (例子来自MSDN)
static_assert(sizeof(void *) == 4, "64-bit code generation is not supported.");
2.3. static_assert的用途
常用在模版编程中 ,对写库的作者用处大
在static_assert的第一个参数 bool_constexpr 中不能有变量表达式
3. 1When to use assertions (何时使用断言)
这里我们指的是assert,运行期的断言。
若某些状况是你预期中的,那么用错误处理;若某些状况永不该发生,用断言)
int n{ 1 } , m{ 0 };
std::cin >> n;
assert((n != 0) && "Divisor cannot be zero!"); // 不合适
int q = m / n;
int n{ 1 } , m{ 0 };
do { // 这是修补bug的代码std::cin >> n; // 断言失败后,要解决这个bug
} while (n == 0); // 在这里编写修复bug的代码
assert((n != 0) && "Divisor cannot be zero!");
int q = m / n;
下面的例子说明了在编译期,静态断言就已经执行了,因为array<int,nums>的nums在编译期就应该知道它的值。
3、声明与定义
1. What is “Declare/Declaration” (什么是声明)
“声明”是引入标识符并描述其类型,无论是类型,对象还是函数。编译器需要该“声明”,以便识别在它处使用该标识符。
extern int bar;extern int g(int, int);double f(int, double); // extern can be omitted for function declarationsclass foo; // no extern allowed for type declarations
2. What is “define/definition” (什么是定义)
“定义”实例化/实现这个标识符。链接器需要“定义”,以便将对标识符的引用链接到标识符所表示的实体。
int bar;int g(int lhs, int rhs) {return lhs*rhs;}double f(int i, double d) {return i+d;}class foo {};
3. Differences between a declaration and a definition (定义与声明的区别)
1、定义有时可取代声明,反之则不行
2、标识符可被声明多次,但只能定义一次
3、 定义通常伴随着编译器为标识符分配内存
【C++grammar】断言与表达式常量相关推荐
- 第 2 章 常量、变量和表达式
<一>继续Hello World 深入了解C语言的注释,注释可以跨行,也可以穿插在程序中.注释的定界符/*和*/,注释需要注意两点:注释不能够嵌套使用,如:/*test1 /* test2 ...
- 常量表达式(constexpr)
首先,常量表达式的概念:在编译期就可以计算出结果的表达式 那么为什么要用常量表达式呢,用常量表达式会有什么好处: 1.允许一些计算只在编译时进行一次,而不是每次程序运行时: 2.编译器可以进行尺度更大 ...
- C++知识整理系列(三)—— constexpr常量表达式
const修饰常量,但是const并未区分编译时常量和运行时常量,而constexpr则只能是编译时常量,在C++11中提出. 这篇文章,将详细讲解constexpr. 目录 一.常量表达式 二.co ...
- C++11 nullptr与常量表达式constexpr记录
1.nullptr (1) nullptr是一个关键字,而nullptr_t是一个类型 typedef decltype(nullptr) nullptr_t 使用nullptr_t类型必须包含#in ...
- Go编程基础 - 常量与运算符
为什么80%的码农都做不了架构师?>>> 常量的定义 常量的值在编译时就已经确定 常量的定义格式与变量基本相同 等号右侧必须是常量或者常量表达式 常量表达式中的函数必须是内置函 ...
- Linq之Expression高级篇(常用表达式类型)
目录 写在前面 系列文章 变量表达式 常量表达式 条件表达式 赋值表达式 二元运算符表达式 一元运算符表达式 循环表达式 块表达式 总结 写在前面 首先回顾一下上篇文章的内容,上篇文章介绍了表达式树的 ...
- golang 常量简介
目录 1.单个常量声明 2.多个常量声明 3.常量表达式 1.单个常量声明 常量可以是全局常量,也可以是函数内部的局部常量.常量的值不可修改,常量表达式的值在编译期计算,而不是在运行期.存储在常量中的 ...
- grep零宽断言正则表达式
一.grep零宽断言: (匹配宽度为零,满足一定的条件/断言) 零宽断言用于查找在某些内容(但并不包括这些内容)之前或之后的东西,也就是说它们像 \b ^ $ \< \> 这样的锚定作用, ...
- CH2-1 类型 操作 表达式
2.1 变量名 (1) 大小写敏感,小写一般做变量,大写做符号常量(symbolic constant) (2) 以字母和_开头,有些类库用了"_" 2.2 数据类型和长度 (1) ...
最新文章
- Html一修改就会自动刷新,web 前端修改 自动刷新 插件使用 liveReload
- OSMboxPost()
- 第二期阿里巴巴 Java Meetup 来北京了。你来么?
- SQL增删改查,基础
- 字体单独设置样式_Glyphs 官方教程 | 字体命名
- 荣耀系列到底算不算华为手机
- 体系结构分析与设计语言AADL基础
- BS7799、ISO/IEC 17799、ISO/IEC 27001的联系与区别
- ab压力 failed_Apache ab压力测试时出现大量的错误原因分析
- webscraper多页爬取_webscraper的常见爬取问题
- 使用xshell登陆腾讯云主机
- 迅雷下载GitHub文件提示需要授权或登录等
- 用PayPal在eBay上撸货加哪种卡可以长期用?
- android开发中论坛帖子图片的排版
- ROS1学习笔记--xacro
- 买卖时机APP 开启股票交易大数据时代!
- 【题解】吉首大学第九届"新星杯"大学生程序设计大赛(重现赛)
- Spring boot实现代理服务器
- mysql 1168_mysql merge报错ERROR 1168
- cocos 《吃星星》---运用Vec2和mag()判断位置和距离
热门文章
- php boolean 全大写还是全小写,【PHP培训】PHP为什么大小写规则是如此不规则?
- android读取excel文件_python里读写excel等数据文件的几种常用方式
- activiti mysql 版本_Mysql8.0.17版本不能自动创建activiti表的坑
- 微信小程序 request请求封装
- Odyssey.js – 使用现成模板在线创建互动的故事
- 【工具相关】web-HTML/CSS/JS Prettify的使用
- CCS3的过渡、变换、动画以及响应式布局、弹性布局
- Laravel 不同环境加载不同的.env文件
- java.lang.IllegalStateException: Connection pool shut down
- Brackets (区间DP)