C++17常量

nullptr

  nullptr出现的目的是为了替代NULL。在某种意义上来说,传统会把NULL,0视为同一种东 西,这取决于编译器如何定义NULL,有些编译器会将定义为((void*)0),有些则会直接将其定义 为0。 

        C++不允许直接将void*隐式转换到其他类型。但如果编译器尝试把NULL定义为((void*)0), 那么在下面这句代码中: 

char *ch = NULL;

        没有了void*隐式转换的C++只好将定义为0。而这依然会产生新的问题,将NULL定义成0,将导致C++中重载特性发生混乱。考虑下面这两个函数: 

void foo(char*);

void foo(int);

        那么foo(NULL)这个语句将会去调用foo(int),从而导致代码违反直觉。 

        为了解决这个问题,C++引入了关键字nullptr,专门用来区分空指针、0。而nullptr的类型 为nullptr_t,能够隐式的转换为任何指针或成员指针的类型,也能和他们进行相等或者不等的比较。 你可以尝试使用clang++编译下面的代码:

#include <iostream>#include <type_traits>//*******1. nullptr******/
// C++17 引入了 std::nullptr_t 类型,它是一个空指针类型。
// 在 C++ 中,NULL 是一个宏,通常定义为 0 或 (void*)0。 
/*int main(){if(std::is_same<decltype(NULL), decltype(0)>::value){std::cout << "NULL is the same type as 0" << std::endl;}else{std::cout << "NULL is NOT the same type as 0" << std::endl;//NULL 和 0 在 C++ 中是不同的类型。}if(std::is_same<decltype(NULL), decltype((void*)0)>::value){std::cout << "NULL is the same type as (void*)0" << std::endl;}else{std::cout << "NULL is NOT the same type as (void*)0" << std::endl;//NULL 和 (void*)0 在 C++ 中是不同的类型。}if(std::is_same<decltype(NULL), std::nullptr_t>::value){std::cout << "NULL is the same type as std::nullptr_t" << std::endl;}else{std::cout << "NULL is NOT the same type as std::nullptr_t" << std::endl;//NULL 和 std::nullptr_t 在 C++ 中是不同的类型。}return 0;
}
*/

        从输出中我们可以看出,NULL不同于与nullptr,0。所以,请养成直接使用的习惯。 此外,在上面的代码中,我们使用了decltype和std::is_same这两个属于现代C++的语法,简 单来说decltype用于类型推导,而std::is_same用于比较两个类型是否相同,我们会在后面 一节中详细讨论。

constexpr

        C++本身已经具备了常量表达式的概念,比如1+2, 3*4这种表达式总是会产生相同的结果并且没 有任何副作用。如果编译器能够在编译时就把这些表达式直接优化并植入到程序运行时,将能增加程序 的性能。一个非常明显的例子就是在数组的定义阶段:

// C++17 引入了 constexpr 关键字,它允许在编译时计算常量表达式。
#include <iostream> 
#define LEN 10/*
int len_foo(){int i = 2;return i;
}constexpr int len_foo_constexpr() {return 5;
}constexpr int fibonacci(const int n) {return  n==1 || n == 2 ? 1 : fibonacci(n - 1) + fibonacci(n - 2);
}int main() {char arr_1[10];                 //合法char arr_2[LEN];                //非法    int len = 10;//char arr_3[len];                //非法const int len_2 = len + 1;constexpr int len_2_constexpr = 1+2+3;//char arr_4[len_2_constexpr];       //合法char arr_4[len_2];       //非法//char arr_5[len_foo()];             //非法char arr_6[len_foo_constexpr() + 1];   //合法std::cout << "fibonacci(10) = " << fibonacci(10) << std::endl; // 输出 55//1, 1, 2, 3, 5, 8, 13, 21, 34, 55std::cout << "fibonacci(10) = " << fibonacci(10) << std::endl; // return 0;}
*/

        上面的例子中char arr_4[len_2]可能比较令人困惑,因为len_2已经被定义为了常量

char arr_4[len_2]为什么仍然是非法的呢?这是因为C++标准中数组的长度必须是一个常量表达式,而对len_2于而言,这是一个const常数,而不是一个常量表达式,因此(即便这种行为在大部分编译器中都支持,但是)它是一个非法的行为,我们需要使用接下来即将介绍的C++11引入的constexpr特性来解决这个问题;而对于arr_5来说,C++98之前的编译器无法得知len_foo()在运行期实际上是返回一个常数,这也就导致了非法的产生。

        注意,现在大部分编译器其实都带有自身编译优化,很多非法行为在编译器优化的加持下会变得合法,若需重现编译报错的现象需要使用老版本的编译器。

        C++11提供了constexpr让用户显式的声明函数或对象构造函数在编译期会成为常量表达式,这个关键字明确的告诉编译器应该去验证len_foo()在编译期就应该是一个常量表达式。此外,修饰的函数可以使用递归:

constexpr int fibonacci(const int n) {return  n==1 || n == 2 ? 1 : fibonacci(n - 1) + fibonacci(n - 2);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/pingmian/82945.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络学习(九)——CDN

一、CDN CDN&#xff08;Content Delivery Network&#xff0c;内容分发网络&#xff09;是一种通过分布式节点将内容更高效地传递给用户的技术架构&#xff0c;广泛应用于加速网站、视频、下载、直播等业务。 CDN 是把内容放到离用户最近的“高速公路入口”&#xff0c;提升访…

Elasticsearch的写入流程介绍

Elasticsearch 的写入流程是一个涉及 分布式协调、分片路由、数据同步和副本更新 的复杂过程,其设计目标是确保数据一致性、可靠性和高性能。以下是写入流程的详细解析: 一、写入流程总览 二、详细步骤解析 1. 客户端请求路由 请求入口:客户端(如 Java 客户端、REST API)…

vue为什么点击两遍才把参数传递过去

先说一下场景&#xff0c;就是我把云服务器这个下拉选择框分别初始化之后&#xff0c;然后点击新建权限然后就打开了右侧的抽屉式的对话框&#xff0c;页面上那个文字信息是传递过来了。那个是正确的&#xff0c;但是我请求接口的时候&#xff0c;发现请求的接口的参数总是要慢…

java代码性能优化

刷题过程中遇到的一些时间复杂度相同&#xff0c;但是常数因子的差距导致的性能差距&#xff0c;遇到持续更新 枚举 VS contains 例如&#xff1a;判断一个字符是不是元音 法一&#xff1a; if(ch a || ch e || ch i || ch o || ch u) 法二&#xff1a; Set<Charact…

OpenGL Chan视频学习-9 Index Buffers inOpenGL

bilibili视频链接&#xff1a; 【最好的OpenGL教程之一】https://www.bilibili.com/video/BV1MJ411u7Bc?p5&vd_source44b77bde056381262ee55e448b9b1973 函数网站&#xff1a; docs.gl 说明&#xff1a; 1.之后就不再单独整理网站具体函数了&#xff0c;网站直接翻译会…

基于微服务架构的社交学习平台WEB系统的设计与实现

设计&#xff08;论文&#xff09;题目 基于微服务架构的社交学习平台WEB系统的设计与实现 摘 要 社交学习平台 web 系统要为学习者打造一个开放、互动且社交性强的在线教育环境&#xff0c;打算采用微服务架构来设计并实现一个社交学习平台 web 系统&#xff0c;以此适应学…

生成式人工智能:重构软件开发的范式革命与未来生态

引言 生成式人工智能&#xff08;GenAI&#xff09;正以颠覆性力量重塑软件开发的底层逻辑。从代码生成到业务逻辑设计&#xff0c;从数据分析到用户交互&#xff0c;GenAI通过其强大的推理能力与场景适应性&#xff0c;将传统开发流程的“复杂工程”转化为“敏捷实验”&#…

C++17原生测试编程实践:现代特性与分支覆盖指南

C17原生测试编程实践&#xff1a;现代特性与分支覆盖指南 概述 本文将深入探讨如何利用C17新特性进行原生测试代码编写&#xff0c;实现完全分支覆盖。我们将不依赖任何外部测试框架&#xff0c;而是使用C17标准库构建完整的测试解决方案。 一、C17测试核心工具集 1. 断言工…

RK3568项目(四)--uboot启动流程之启动模式选择

目录 一、引言 二、芯片初始化 ------>2.1、io_domain ------>2.2、调频调压 ------>2.3、控制台初始化 三、平台初始化 ------>3.1、设置mac地址 ------------>3.1.1、vendor分区 ------>3.2、设置serialno ------>3.3、设置下载模式 -------…

Kotlin JVM 注解详解

前言 Kotlin 作为一门现代 JVM 语言&#xff0c;提供了出色的 Java 互操作性。为了更好地支持与 Java 代码的交互&#xff0c;Kotlin 提供了一系列 JVM 相关注解。这些注解不仅能帮助我们控制 Kotlin 代码编译成 Java 字节码的行为&#xff0c;还能让我们的 Kotlin 代码更好地…

Starrocks 物化视图的实现以及在刷新期间能否读数据

背景 本司在用Starrocks做一些业务上的分析的时候&#xff0c;用到了物化视图&#xff0c;并且在高QPS的情况下&#xff0c;RT也没有很大的波动&#xff0c;所以在此研究一下Starrock的实现&#xff0c;以及在刷新的时候是不是原子性的 本文基于Starrocks 3.3.5 结论 Starro…

[网页五子棋][对战模块]前后端交互接口(建立连接、连接响应、落子请求/响应),客户端开发(实现棋盘/棋子绘制)

文章目录 约定前后端交互接口建立连接建立连接响应针对"落子"的请求和响应 客户端开发实现棋盘/棋子绘制部分逻辑解释 约定前后端交互接口 对战模块和匹配模块使用的是两套逻辑&#xff0c;使用不同的 websocket 的路径进行处理&#xff0c;做到更好的耦合 建立连接 …

电工基础【2】自锁、互锁、正反转电路

04 自锁、正反转电路 我们讲一下这个自锁和正反转。 自锁电路图示例图 加了一个这个 KM1 自锁。加了 KM1 的辅助触头&#xff0c;它怎么实现呢&#xff1f;它怎么就自锁了呢&#xff1f;没加它的时候为什么是点动&#xff1f;加它为什么自锁&#xff1f; 讲解一下。首先我们…

TypeScript 中感叹号(!)两种位置用法

这是一个非常好的问题&#xff01; 在 TypeScript 中&#xff0c;感叹号&#xff08;!&#xff09;有两种位置用法&#xff0c;它们含义完全不同&#xff1a; ✅ 一、后置感叹号 !&#xff08;非空断言&#xff09; process.env.ADMIN_PRIVATE_KEY! ✅ 作用&#xff1a; 告…

t014-项目申报管理系统 【springBoot 含源码】

项目演示视频 摘 要 传统信息的管理大部分依赖于管理人员的手工登记与管理&#xff0c;然而&#xff0c;随着近些年信息技术的迅猛发展&#xff0c;让许多比较老套的信息管理模式进行了更新迭代&#xff0c;项目信息因为其管理内容繁杂&#xff0c;管理数量繁多导致手工进行…

【C++】STL详解(四)---Stack和Queue

文章目录 Stack定义方式使用方式 Queue定义方式使用方式 Stack Stack是一种容器&#xff0c;是基本的数据结构之一&#xff0c;特点是先进后出。 定义方式 方式一&#xff1a;普通定义方式 stack<int> st1;方式二&#xff1a; stack<int,vector<int>> …

解决 xmlsec.InternalError: (-1, ‘lxml xmlsec libxml2 library version mismatch‘)

解决 xmlsec.InternalError: (-1, ‘lxml & xmlsec libxml2 library version mismatch’) 错误信息如下&#xff1a; Traceback (most recent call last):File "/home/mobsf/Mobile-Security-Framework-MobSF/manage.py", line 18, in <module>execute_f…

SpringBoot自定义实体类字段的校验注解

在Spring Boot项目中&#xff0c;我们经常需要对请求参数进行格式或业务规则的校验。虽然Spring Boot提供了如NotNull、Size等基础校验注解&#xff0c;但在实际开发中往往无法满足复杂的业务需求。但是在Controller层写大量的 if 语句的判断逻辑又实在不优雅&#xff0c;好在 …

实现单例模式的6种方法(Python)

目录 一. 基于模块的实现(简单&#xff0c;易用) 二. 重新创建时报错(不好用) 三. 只靠方法获取实例(不好用) 四. 类装饰器 五. 重写__new__方法 六. 元类 七. 总结 单例模式&#xff08;Singleton Pattern&#xff09;是一种设计模式&#xff0c;其核心目标是确保一个类…

循环神经网络(RNN)全面教程:从原理到实践

循环神经网络(RNN)全面教程&#xff1a;从原理到实践 引言 循环神经网络(Recurrent Neural Network, RNN)是处理序列数据的经典神经网络架构&#xff0c;在自然语言处理、语音识别、时间序列预测等领域有着广泛应用。本文将系统介绍RNN的核心概念、常见变体、实现方法以及实际…