总述

    又来更新了,今天带来的是nullptr空指针常量、constexpr(常量表达式)C++的两个用法。Result result_fun = nullptr;constexpr static uint32_t try_times = 100;这是两个在工作中常用的C++操作,但是你知道nullptr和constexpr由来以及它们的更多用法吗?

下面听我一一道来。

作者:良知犹存

转载授权以及围观:欢迎添加微信公众号:羽林君

一、nullptr

C++11要引入nullptr?它与NULL相比又有什么不同呢?

加上nullptr,我们就有下面三种方法来获取一个“空指针”:

int *p1 = NULL;
int *p2 = 0;
int *p3 = nullptr;
 

空指针是不会指向有效数据的指针。以前,C++在源代码中使用0表示这种指针,但内部表示可能不同。这带来了一些问题,因为这使得0既可以表示指针常量,又可表示整形常量。

所以C++11新增了关键字nullptr,用于表示空指针;它是指针类型,不能转化为整形类型。为向后兼容,C++11仍然允许0来表示空指针,因此表达式nullptr=0为true,但使用nullptr而不是0提供了更高的类型安全。例如,可将0传递给接受int参数的函数,但如果您试图将nullptr传递给这样的函数,编译器将此视为错误。因此,出于清晰和安全的考虑,请使用nullptr——如果你的编译器支持它。

空指针常量nullptr注意事项:

(1) 可以隐式转换为任意类型的指针或者指向任何成员。
(2) 不能隐式转换为整型,可以隐式转换为bool类型代表false。
(3) 可以和除了整型和bool型的其他类型比较。

二、constexptr

常量表达式(const expression)是指值不会改变并且在编译过程就能得到计算结果的表达式。显示,字面值属于常量表达式,用表达式初始化的const对象也是常量表达式。后面会提到,C++语言中有几种情况是要用到常量表达式的。

一个对象(或表达式)是不是常量表达式由它的数据类型和初始值共同决定,例如

const int max_num = 20;           // max_num是常量表达式
const int limit = max_num + 1; // limit 是常量表达式
int staff_size = 2; // staff_size 不是常量表达式,因为staff_size没有用const修饰
const int sz = get_size(); // sz 不是常量表达式,虽然sz是个常量,但它的值在运行时才能确定
 

尽管staff_size 的初始值是个字面值常量,但由于它的数据类型只是一个普通的int  而非const int,所以它不属于常量表达式。另一方面,尽管sz是一个常量,但它的具体值要等到运行时才能获取到,所以也不是常量表达式。

const变量:

在一个复杂系统中,很难分辨一个初始值到底是不是常量表达式。当然也可以定义一个const变量并把它的初始值设为我们认为的某个常量表达式,但在实际使用时,尽管要求如此却常常发现初始值并非常量表达式的情况。可以这么说,在此种情况下,对象的定义和使用根本就是两回事。

C++11新标准规定,允许将变量声明为constexpr类型以便编译器来验证变量的值是否是一个常量表达式。声明为constexpr的变量一定是一个常量,而且必须用常量值表达式初始化:

constexpr int mf = 20;    // mf是常量表达式
constexpr int limit = mf + 1; // limit 是常量表达式
​constexpr int sz = get_sz(); // 只有当 get_sz() 是一个 constexpr 函数时才是一条正确的声明语句

字面值类型:    常量表达式的值需要在编译时就得到计算,因此对声明constexpr时用到的类型必须有所限制。因为这些类型一般比较简单,值也显而易见、容易得到,就把它们称为“字面值类型”(interal type)。    到目前为止接触过的数据类型中,算术类型、引用和指针都属于字面值类型。自定义类 Sales_item、IO库、string 类型则不属于字面值类型,也就不能被定义为constexpr。    尽管指针和引用都能定义成constexpr,但它们的初始值却受到严格限制。一个constexpr指针的初始值必须是nullptr或者是0,或者是存储于某个固定地址中的对象。而函数体内定义的变量一般来说并非存放到固定地址中,因此constexpr之指针不能只想这样的变量。(对于程序执行中各个变量分配的地址不明白的,可以点击链接看我之前的一篇文章)
    相反的,定义于所有函数体之外的对象其地址固定不变,能用来初始化constexpr指针。
指针和constexper:
    必须明确一点,在constexpr声明中如果定义了一个指针,限定符constexpr仅对指针有效,与指针所指的对象无关:

const int *p = nullptr;    // p 是一个指向整型常量的指针
constexpr int *q = nullptr; // q 是一个指向整数的常量指针,constexpr 仅对指针有效

p和q的类型相差甚远,p是一个指向常量的指针,而q是一个常量指针,其中关键在于constexpr把它所定义的对象置为了顶层 const类似于int * const  p = nullptr;    与其他常量指针类似,constexpr指针既可以指向常量也可以指向一个非常量

constexpr int *np  = nullptr;//np是一个指向整数的常量指针,其值为空
int j= 0;
constexpr int i=42;//i的类型是整型常量

i和j都必须定义在函数体之外
constexpr const int *p = &i;//p是指针常量,指向整型常量i
constexpr int *p1 = &j; //p1是常量指针,指向整数j

constexpr函数:

尽管不能使用普通函数作为constexpr变量的初始值,但新标准允许定义一种特殊的constexpr函数。这种函数应该足够简单以使得编译时就可以计算其结果,这样就能用constexpr函数去初始化constexpr变量了。

constexpr函数的限制

(1) 函数中只能有一个return语句(有极少特例)

(2) 只能调用其他constexpr函数。

(3) 只能使用全局constexpr变量。

(4) 递归并不受限制,但只允许一个返回语句,可以使用三元运算符。

(5) constexpr函数,只允许包含一行可执行代码。但允许包含typedefs、using declaration&&directives、静态断言等。

(6) 一个声明为constexpr的函数同样可以在运行时被调用,即当这个函数的参数是非常量的时候。

constexpr函数是只能用于常量表达式的函数。不同于一般函数,constexpr 函数的返回值类型及所有形参的类型都是字面值类型(算术类型,引用,指针等属于字面值类型),而且函数体中有且只有一条 return 语句。为了能在编译过程中随之展开,constexpr函数被隐式地指定为内联函数。constexpr 函数的返回值在编译时就能被确定。

我们允许 constexpr 函数不一定返回常量表达式,但是我们认为: 如果 arg 为常量表达式,则 scale(arg)也是常量表达式

#include <iostream>

constexpr size_t scale(size_t cnt) {
return 2 * cnt;
} int main () {
constexpr size_t sz;
constexpr size_t s = 3;
sz = scale(s);
std::cout << sz << std::endl;
return 0;
}
 

可见,constexpr 函数不一定返回常量表达式,但是在 scale(3) 可以在编译时确定。

大家平时是怎么用的呢?

参与讨论

这就是我分享的c++的nullptr和constexpr,如果大家有什么更好的思路,欢迎分享交流哈。

参考:C++Primer Plus (第5版)、C++Primer Plus (第6版)

https://blog.csdn.net/JinhuCheng/article/details/87545143?utm_medium=distribute.pc_relevant.none-task-blog-title-1&spm=1001.2101.3001.4242

https://blog.csdn.net/woxiaohahaa/article/details/78512576

更多分享,扫码关注我

c++nullptr(空指针常量)、constexpr(常量表达式)的更多相关文章

  1. C++11特性——变量部分(using类型别名、constexpr常量表达式、auto类型推断、nullptr空指针等)

    #include <iostream> using namespace std; int main() { using cullptr = const unsigned long long ...

  2. C++11 constexpr常量表达式

    常量表达式函数 要求: 函数体内只有单一的return返回语句 例如: constexpr int data() { const int i=1; //含有除了return以外的语句 return i ...

  3. 速战速决 (1) - PHP: 概述, 常量, 变量, 运算符, 表达式, 控制语句

    [源码下载] 速战速决 (1) - PHP: 概述, 常量, 变量, 运算符, 表达式, 控制语句 作者:webabcd 介绍速战速决 之 PHP 概述 常量 变量 运算符 表达式 控制语句 示例1. ...

  4. C++中指针常量和常量指针的区别

    在C++学习使用过程中,每个人都不可避免地使用指针,而且都或多或少的接触过常量指针或指针常量,但是对这两个的概念还是很容易搞糊涂的. 本文即是简单描述指针常量和常量指针的区别. 常量指针 定义: 又叫 ...

  5. 【转】C++易混知识点1: 指针常量和常量指针的区别,附有详细案例解释

    熟悉C++也已经有一些年头了,今天突然翻出当年浏览的书籍,对一些概念居然生疏了,指针常量和常量指针由于 指针 这一特殊的对象而变得难以区别.因此,在思考再三之后,决定写下该篇总结,加强对他们的区别: ...

  6. Const用法总结(快速区分指针常量与常量指针)

    想当初面试时,面试官问我熟悉C++么?熟悉的话说一下const的用法,然后我就开始凌乱了~ 其实const的用处还真不少,好好捋顺一下会有很大的帮助. 有时候我们希望定义一种常量,它的值不能被修改,这 ...

  7. c++指针常量和常量指针概述

    个人理解,欢迎指正 这个简单,简单,简单(不要有心里压力:认为很难) 本文将会解决:  A.变与不变 B.判断指针常量和常量指针. C.常量指针指针常量.本文不涉及. 1.概述 A.指针: 说到底,还 ...

  8. C和指针 第三章 指针常量与常量指针

    c语言中声明常量的两种方式 const int value int const value 如果要声明常量的指针,即指向常量的指针,则可以参考上面的常量声明修改一下 const int *ptr in ...

  9. 06 java中常量以及常量池

    1.举例说明 变量 常量 字面量 int a=10; float b=1.234f; String c="abc"; final long d=10L; a,b,c为变量,d为常量 ...

  10. C++(二十) — 指针常量和常量指针

    1.const 常量概念 对于 const 定义的常量,必须在定义时初始化,不能在程序执行运行过程中改变. 2.指针常量.常量指针 区别 (1)技巧:从右向左读,替代方法: p:换为  p is a: ...

随机推荐

  1. Spring的自动装配与依赖注入

    Spring的自动装配与依赖注入 装配 = 创建Bean + 注入Bean 创建Bean 自动发现 显式注册Bean 注入Bean 基于配置的注入 自动注入 Spring的装配分为显式装配和隐式装配, ...

  2. LRU缓存的实现

    文章目录 LRU简介 LRU算法分析 实现代码 节点类 双向链表 LRUCache类 测试类 总结 LRU简介 LRU是"Least Recently Used"的简写,意思是最近 ...

  3. 【Java并发集合】ConcurrentHashMap源码解析基于JDK1.8

    concurrentHashMap(基于jdk1.8) 类注释 所有的操作都是线程安全的,我们在使用时无需进行加锁. 多个线程同时进行put.remove等操作时并不会阻塞,可以同时进行,而HashT ...

  4. ThinkPHP5表单令牌刷新

    制作登录页面的时候,加入了表单令牌,账号和密码输入错误后,再登录的话,会提示表单令牌错误, 这是因为旧的令牌已经过期了,我们要处理下前端的token,修复的办法,在路由文件下加入 //刷新表单令牌,然 ...

  5. JAVA之JDBC数据库连接池总结篇

    JDBC数据库连接池 一.JDBC数据库连接池的必要性 二.数据库连接池技术 三.多种开源的数据库连接池 3.1 C3P0数据库连接池 3.2 DBCP数据库连接池 3.3 Druid(德鲁伊)数据库 ...

  6. 攻防世界-crypto-easychallenge(.pyc反编译)

    进入题目后下载附件,发现是一个.pyc文件. pyc是一种二进制文件,是由py文件经过编译后,生成的文件,是一种byte code,py文件变成pyc文件后,运行加载的速度会有所提高:另一反面,把py ...

  7. ctfhub技能树—web前置技能—http协议—Cookie

    打开靶机环境 查看显示内容 根据提示,需要admin登录才能得到flag 题目介绍为Cookie欺骗.认证.伪造 介绍一下cookie和session 一.cookie: 在网站中,http请求是无状 ...

  8. oracle编译表上失效USERDBY脚本

    对表进行DLL操作之后,依赖这个表的一些存储过程,触发器等会失效,可以用下边的脚本进行重编译 /* Formatted on 2020/7/8 上午 09:31:31 (QP5 v5.163.1008 ...

  9. 记录list.remove()和list.pop()

    list.remove(obj):这个是移除列表中某个值的第一个匹配项 list.pop(index):这个是移除列表中下标为index的元素 当元素全是数字或者有数字时注意区分.

  10. python(re正则)

    import re #导入模块   info = 'qwewwer12332423kdsjfkl2342kdjfl213nkafal123123' 例1: res1 = re.compile('er( ...