const、inline、nullptr的使用

news/2024/9/23 9:33:48/

目录

1.const引用

1.1权限的放大 

1.2权限的缩小

2.inline

3.nullptr


1.const引用

可以引用一个const对象,但是必须用const引用。const引用也可以引用普通对象,因为对象的访 问权限在引用过程中可以缩小,但是不能放大。
不需要注意的是类似 int& rb = a*3; double d = 12.34; int& rd = d; 这样一些场 景下a*3的和结果保存在一个临时对象中, int& rd = d 也是类似,在类型转换中会产生临时对 象存储中间值,也就是时,rb和rd引用的都是临时对象,而C++规定临时对象具有常性,所以这里 就触发了权限放大,必须要用常引用才可以。
所谓临时对象就是编译器需要⼀个空间暂存表达式的求值结果时临时创建的⼀个未命名的对象, C++中把这个未命名对象叫做临时对象。

1.1权限的放大 

int main() {//权限的放大,a只能读值,不能更改,当取a的别名时,b可读值与改值,会报错const int a = 10;//int& b = a;const int& b = a;//这种写法为正确return 0;
}

1.2权限的缩小

int main() {// 这⾥的引⽤是对b访问权限的缩⼩int b = 20;const int& rb = b;return 0;
}

注:在之后的编写中,只能出现权限的缩小,不能出现权限的放大

2.inline

inline修饰的函数叫做内联函数,编译时C++编译器会在调用的地方展开内联函数,这样调用内联 函数就需要建立栈帧了,就可以提高效率。
inline对于编译器而言只是一个建议,也就是说,你加了inline编译器也可以选择在调用的地方不展 开,不同编译器关于inline什么情况展开各不相同,因为C++标准没有规定这个。inline适用于频繁 调用的短小函数,对于递归函数,代码相对多小些的函数,加上inline也会被编译器忽略。
C语言实现宏函数也会在预处理时替换展开,但是宏函数实现很复杂很容易出错的,且不方便调 试,C++设计了inline目的就是替代C的宏函数。
vs编译器 debug版本下面默认是不展开inline的,这样方便调试,debug版本想展开需要设置⼀下 以下两个地方。
inline不建议声明和定义分离到两个文件,分离会导致链接错误。因为inline被展开,就没有函数地 址,链接时会出现报错。

inline(内敛函数)与宏函数类似 

#include<iostream>using namespace std;//#define ADD(a, b) ((a) + (b))宏函数
inline int Add(int x, int y)
{int ret = x + y;ret += 1;ret += 1;ret += 1;return ret;
}
int main()
{// 可以通过汇编观察程序是否展开// 有call Add语句就是没有展开,没有就是展开了int ret = Add(1, 2);cout << Add(1, 2) * 5 << endl;return 0;
}

 编写上面代码,会显示报错,是因为inline不建议声明和定义分离到两个文件,分离会导致链接错误。因为inline被展开,就没有函数地址,链接时会出现报错。

此时我们需要下方操作:

3.nullptr

NULL实际是一个宏,在传统的C头文件(stddef.h)中,可以看到如下代码:
# ifndef NULL
       # ifdef __cplusplus
              # define NULL 0
       # else
              # define NULL ((void *)0)
       # endif
# endif
C++中NULL可能被定义为字面常量0,或者C中被定义为无类型指针(void*)的常量。不论采取何种 定义,在使用空值的指针时,都不可避免的会遇到⼀些麻烦,本想通过f(NULL)调⽤指针版本的 f(int*)函数,但是由于NULL被定义成0,调⽤了f(int x),因此与程序的初衷相悖。f((void*)NULL); 调用会报错。
C++11中引入nullptr,nullptr是⼀个特殊的关键字,nullptr是一种特殊类型的字面量,它可以转换 成任意其他类型的指针类型。使用nullptr定义空指针可以避免类型转换的问题,因为nullptr只能被 隐式地转换为指针类型,而不能被转换为整数类型。
#include<iostream>
using namespace std;
void f(int x)
{
cout << "f(int x)" << endl;
}
void f(int* ptr)
{
cout << "f(int* ptr)" << endl;
}
int main()
{
f(0);
// 本想通过f(NULL)调⽤指针版本的f(int*)函数,但是由于NULL被定义成0,调⽤了f(int
x),因此与程序的初衷相悖。
f(NULL);
f((int*)NULL);// 编译报错:error C2665: “f”: 2 个重载中没有⼀个可以转换所有参数类型
// f((void*)NULL);f(nullptr);return 0;
}

nullptr大大减少了我们对null指针访问报错的风险!!!!


http://www.ppmy.cn/news/1517455.html

相关文章

数据世界的新篇章:精通INSERT INTO数据插入艺术

标题&#xff1a;数据世界的新篇章&#xff1a;精通INSERT INTO数据插入艺术 在数据库管理的宏伟画卷中&#xff0c;INSERT INTO语句扮演着至关重要的角色。它是将新数据记录插入到表中的基石。本文将带领你深入理解INSERT INTO语句的精髓&#xff0c;并通过丰富的代码示例&am…

Node.js原生开发脚手架工具(下)

前言 在现代软件开发中&#xff0c;脚手架工具成为提高开发效率和一致性的关键利器。使用Node.js原生开发自己的脚手架工具不仅能帮助自动化常见任务&#xff0c;还能根据具体需求进行高度定制。Node.js的异步非阻塞特性和丰富的模块系统使其成为构建这种工具的理想选择。本篇文…

JavaEE-TCP协议

上篇文章介绍了TCP可靠传输主要依靠的确认应答和超时重传机制&#xff0c;超时重传是确认应答的重要补充&#xff0c;还介绍了TCP的连接管理机制。本篇文章补充上一篇文章的TCP十个常用核心机制的其他七个。 目录 滑动窗口 窗口大小 流量控制 拥塞控制 延时应答 捎带应答…

Launcher3 长按Hotseat图标,显示删除角标(红底白杠杠用于删除图标或者显示应用未读消息数量)

基于Android 13,Launcher3实现需求&#xff1a; 1. 长按Hotseat的图标显示红色删除角标 2. 点击角标&#xff0c;删除图标并保存到Database 3.点击其他地方&#xff0c;取消编辑hotseat图标模式 实现效果&#xff1a; 实现原理&#xff1a; 图标是由BubbleTextView来是实现…

【XR】优化SLAM SDK的稳定性

优化SLAM SDK的稳定性是确保增强现实 (AR) 和虚拟现实 (VR) 应用在各种环境和设备上都能稳定运行的关键。以下是一些主要的优化方法&#xff1a; 1. 传感器融合优化 方法: 将多个传感器的数据&#xff08;如摄像头、加速度计、陀螺仪、磁力计&#xff09;进行融合&#xff0c…

Docker基础概述、Docker安装、Docker镜像加速、Docker镜像指令

1.为什么学docker 开发环境与测试环境不同&#xff0c;导致错误 因此docker提供解决方法———系统平滑移植&#xff0c;容器虚拟化技术 将代码与软件与配置文件 打包成一个镜像 2.docker的历练 创建一个开发环境内成为镜像文件再用docker使用镜像 3.什么是docker Docke…

提升学术论文质量的智能助手:ChatGPT

提升学术论文质量的智能助手&#xff1a;ChatGPT 前言ChatGPT的核心功能ChatGPT的优势具体应用案例局限性与最佳实践结语 前言 在这个知识爆炸的时代&#xff0c;学术研究已成为推动社会进步和科技发展的重要力量。每一篇论文的撰写&#xff0c;都是对人类知识边界的一次探索和…

Kotlin 泛型小知识: `<T>`, `<out T>`, `<in T>` 的区别

引言 我们是不是常常在 Kotlin 的代码中看到一些奇怪的符号&#xff0c;比如 <out T> 或者 <T>&#xff1f;如果我们对这些泛型&#xff08;Generics&#xff09;符号还不太了解&#xff0c;没关系&#xff01;今天我们就来聊一聊它们的区别&#xff0c;以及如何在…