C++ Primer Chapter 2 Variables and Basic Types

C++ Primer Chapter 2 Variables and Basic Types

2024/05/27
2.3 复合类型
引用
定义
通过将声明符写成&d的形式来定义引用类型,其中d是声明的变量名。
int ival=1024;
int &refVal=ival;
int &refVal2;
//报错:引用必须被初始化

引用即别名
引用并非对象,相反的,它只是为一个已经存在的对象所起的另外一个名字。

定义了一个引用之后,对其进行的所有操作都是在与之绑定的对象上进行的:
refVal=2;
int ii=refVal;

为引用赋值,实际上是把值付给了与引用绑定的对象。
获取引用的值,实际上获取了与引用绑定的对象的值。
以引用作为初始值,实际上是以与引用绑定的对象作为初始值:

int &refVal3=refVal; //正确,refVal3绑定到了那个与refVal绑定的对象上,这里就是绑定在ival上
int i=refVal //正确:i被初始化为ival的值

因为引用不是一个对象,所以不能定义引用的引用。

指针

指针本身就是一个对象,允许对指针进行赋值和拷贝,而且在指针的声明周期内它可以先后指向几个不同的对象。
指针无须在定义时赋初值。和其他内置类型一样,在块作用域内定义的指针如果没有被初始化,也将拥有一个不确定的值。

定义
int ival=42;
int *p=&ival;
取地址符(&)
指针值

指针的值(即地址)应属于下列4种状态之一:
1.指向一个对象。
2.指向紧邻对象所占空间的下一个位置。
3.空指针,意味着指针没有指向任何对象。
4.无效指针,也就是上述情况之外的其他值。

解引用符(*)
int ival=42;
int *p=&ival; //p存放着变量ival的地址,或者说p是指向变量ival的指针。

cout<<p; //由符号得到指针p所指的对象,输出42

p=0; //由符号得到指针p所指的对象,即可经由p为变量ival赋值

cout<<*p; //输出0

Note 解引用操作仅适用于那些确实指向了某个对象的有效指针。

空指针(null pointer)不指向人很对象,在试图使用一个指针之前可以首先检查它是否为空。

以下列出了几种生成空指针的方法:
int *p1=nullptr;
int *p2=0;
//需要首先#include cstdlib
int *p3=NULL;

把int变量直接赋值给指针是错误的操作,即使int变量的值恰好等于0也不行。
int zero=0;
int *pi=zero; //错误:不能把int变量直接赋给指针
建议:初始化所有指针

赋值和指针
赋值永远改变的是等号左侧的对象

其他指针操作
指针用在条件表达式中
int ival=1024;
int *pi=0; //pi合法,是一个空指针
int *pi2=&ival; //pi2是一个合法的指针,存放着ival的地址

if(pi) //pi的值是0,因此条件的值是false
//
if(pi2) //pi2指向ival,因此它的值不是0,条件的值是true
//

void*指针

void是一种特殊的指针类型,可用于存放任意对象的地址。一个void指针存放着一个地址,这一点和其他指针类似。不同的是,我们对该地址中到底是个什么类型的对象并不了解:

2.3.3理解复合类型的声明
WARNING 很多程序员容易迷惑于基本数据类型和类型修饰符的关系,其实后者不过是声明符的一部分罢了。

指向指针的引用
引用本身不是一个对象,因此不能定义指向引用的指针。但指针是对象,所以存在对指针的引用:
int i=31;
int *p; //p是一个int型指针
int *&r=p; //r是一个对指针p的引用
r=&i; //r引用了一个指针,因此给r赋值&i就是令p指向i
*r=0; //解引用r得到i,也就是p指向的对象,将i的值改为0

要理解r的类型到底是什么,最简单的办法是从右向左阅读r的定义。离变量名最近的符号(此例中的是&r的符号&)对变量的类型有最直接的影响,因此r是一个引用。声明符的其余部分用以确定r引用的类型是什么,此例中的符号*说明r引用的是一个指针,最后,声明的基本数据类型部分指出r引用的是一个int指针。
Tip 面对一条比较复杂的指针或引用的声明语句时,从右向左阅读有助于弄清楚它的真实含义。

2.4 const限定符
因为const对象一旦创建后其值就不能再改变,所以const对象必须初始化。一如既往,初始值可以是任意复杂的表达式:

只能在const类型的对象上执行不改变其内容的操作

在不改变const对象的操作中还有一种是初始化,如果利用一个对象去初始化另外一个对象,则它们是不是const都无关紧要。

默认情况下,const对象仅在文件内有效。
当多个文件中出现了同名的const变量时,七十年等同于在不同文件中分别定义了独立的变量。
Note 如果想在多个文件之间共享const对象,必须在变量的定义之前添加extern关键字。

2.4.1 const的引用

初始化和对const的引用

初始化常量引用时允许用任意表达式作为初始值,只要该表达式的结果能转换成引用的类型即可。
int i = 31;
const int& r1 = i;
const int& r2 = 31; //r2也绑定对象i,但是不允许通过r2修改i的值
const int& r3 = r1 * 2;
//非常量引用的初始值必须为左值
//int& r4 = r2*2;

对const的引用可能引用一个并非const的对象

2.4.2 指针和const
指向常量的指针不能用于改变其所指对象的值。
要想存放常量对象的地址,只能使用指向常量的指针;

和常量引用一样,指向常量的指针也没有规定其所指的对象必须是一个常量。所谓指向常量的指针仅仅要求不能通过该指针改变对象的值,而没有规定那个对象的值不能通过其他途径改变。

Tip 试试这样想把:所谓指向常量的指针或引用,不过是指针或引用的“自以为是”罢了,他们觉得自己指向了常量,所以自觉地不去改变所指对象的值。

const指针
允许把指针本身定位常量。常量指针(const pointer)必须初始化,而且一旦初始化完成,则它的值(也就是存放在指针中的那个地址)就不能再改变了。
把*放在const关键字之前用以说明指针是一个常量,这样的书写形式隐含了一层意味,即不变的是指针本身的值而非指向的那个值:

指针本身是一个常量并不意味着不能通过指针修改其所指对象的值,能否这样做完全依赖于所指对象的类型。

2.4.3 顶层const
指针本身是一个对象,它又可以指向另外一个对象。因此,指针本身是不水常量一级指针所指的是不是一个常量就是两个相互独立的问题。用名词顶层const(top-level const)表示指针本身是个常量,而用名词底层const(low-level const)表示指针所指的对象是一个常量。
更一般的,顶层const可以表示任意的对象是常量,这一点对任何数据类型都适用,如算法类型、类、指针等。底层const则与指针和引用等复合类型的基本类型部分有关。
比较特殊的是,指针即可以是顶层const也可以是底层const,这一点与其他类型相比区别明显。

当执行对象的拷贝操作时,常量是顶层const还是底层const区别明显。
其中,顶层const不受什么影响:
执行拷贝操作并不会改变被拷贝对象的值,因此,拷入和拷出的对象是否是常量都没什么影响。
另一方面,底层const的限制却不能忽视。
当执行对象的拷贝操作时,拷入和拷出的对象必须具有相同的底层const资格,或者两个对象的数据类型必须能够转换。
一般来说,非常量可以转换为常量,反之则不行。

2.4.4 constexpr和常量表达式

常量表达式(const expression)是指值不会改变并且在编译过程就能得到计算结果的表达式。
一个对象(或表达式)是不是常量表达式由它的数据类型和初始值共同决定。
2.4.4 constexpr和常量表达式

常量表达式(const expression)是指值不会改变并且在编译过程中就能得到计算结果的表达式。
一个对象(或表达式)是不是常量表达式由它的数据类型和初始值共同决定的。

const int max_files=20;				//max_files是常量表达式
const int limit=max_files+1;		//limit是常量表达式
int staff_size=27;					//staff_size不是常量表达式
const int sz=get_size();			//sz不是常量表达式,尽管sz本身是一个常量,但它的具体值知道运行时才能获取到,所以不是常量表达式。

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

constexpr int sz=size();			//只有当size是一个constexpr函数时才是一条正确的声明

尽管不能使用普通函数作为constexpr变量的初始值,但是,新标准允许定义一种特殊的constexpr函数。这种函数应该足够简单以使得编译时就可以计算其结果,这样就能用constexpr函数去初始化constexpr变量了。
字面值类型
算数类型、引用和指针都属于字面值类型。
自定义类、IO库、string类型则不属于字面值类型,也就不能被定义成constexpr。

指针与constexpr

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

constexpr把它所定义的对象置为了顶层const。

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

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

相关文章

script 标签中 defer 和 async 属性的区别

script 标签中的 defer Vs. async 在 HTML 中&#xff0c;script 标签可以使用 defer 和 async 属性来控制外部 JavaScript 脚本加载和执行的方式。defer 和 async 都可以提高页面的加载性能&#xff0c;主要区别整理如下。 区别点deferasync加载顺序按顺序加载异步加载&…

论文笔记:Vision GNN: An Image is Worth Graph of Nodes

neurips 2022 首次将图神经网络用于视觉任务&#xff0c;同时能取得很好的效果 1 方法 2 架构 在计算机视觉领域&#xff0c;常用的 transformer 通常是 isotropic 的架构&#xff08;如 ViT&#xff09;&#xff0c;而 CNN 更喜欢使用 pyramid 架构&#xff08;如 ResNet&am…

开源数据库同步工具DBSyncer

前言&#xff1a; 这么实用的工具&#xff0c;竟然今天才发现&#xff0c;相见恨晚呀&#xff01;&#xff01;&#xff01;&#xff01; DBSyncer&#xff08;英[dbsɪŋkɜː]&#xff0c;美[dbsɪŋkɜː 简称dbs&#xff09;是一款开源的数据同步中间件&#xff0c;提供M…

必看项目|多维度揭示心力衰竭患者生存关键因素(生存分析、统计检验、随机森林)

1.项目背景 心力衰竭是一种严重的公共卫生问题,影响着全球数百万人的生活质量和寿命,心力衰竭的病因复杂多样,既有个体生理因素的影响,也受到环境和社会因素的制约,个体的生活方式、饮食结构和医疗状况在很大程度上决定了其心力衰竭的风险。在现代社会,随着生活水平的提…

使用moquette mqtt发布wss服务

文章目录 概要一、制作的ssl证书二、配置wss小结 概要 moquette是一款不错的开源mqtt中间件&#xff0c;github地址&#xff1a;https://github.com/moquette-io/moquette。我们在发布mqtt服务的同时&#xff0c;是可以提供websocket服务器的&#xff0c;有些场景下需要用到&a…

OpenAI新模型开始训练!GPT6?

国内可用潘多拉镜像站GPT-4o、GPT-4&#xff08;更多信息请加Q群865143845&#xff09;: 站点&#xff1a;https://xgpt4.ai0.cn/ OpenAI 官网 28 日发文称&#xff0c;新模型已经开始训练&#xff01; 一、新模型开始训练 原话&#xff1a;OpenAI has recently begun training…

价值飙升30%,AI PC拉动半导体出货潮

由于处理器和DRAM的升级&#xff0c;大摩预测每台AI PC的半导体价值将增长20%-30%&#xff0c;PC平均售价也将提高7%。 台北国际电脑展即将于6月2日隆重开幕。 随着展会的临近&#xff0c;各种现象级的AI PC也蓄势待发。 就在上周&#xff0c;联想在业绩会上&#xff0c;首次…

2-EMMC启动及各分区文件生成过程

EMMC的使用比nand flash还是复杂一些&#xff0c;有其特有的分区和电器性能 1、启动过程介绍 跟普通nand或spi flash不同&#xff0c;uboot前面还有好几级 在vendor某些厂商的设计中&#xff0c;ATF并不是BOOTROM加载后的第一个启动镜像&#xff0c;可能是这样的&#xff1a; …

java的方法重写

重写的概述 重写是基于继承来说的&#xff0c;因为父类的方法需求不满足于子类&#xff0c;所以就要在进行方法重写&#xff0c;如果不知道继承是啥可以看我上一篇笔记 在这里用代码举个栗子 例如&#xff1a;我们定义了一个动物类代码如下&#xff1a; public class Animal…

Leecode热题100---二分查找--4:寻找两个正序数组的中位数

题目&#xff1a; 给定两个大小分别为 m 和 n 的正序&#xff08;从小到大&#xff09;数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。 解法1、暴力解法&#xff08;归并&#xff09; 思路&#xff1a; 合并 nums1&#xff0c;nums2 为第三个数组 排序第三个数…

XXL-JOB分布式任务调度框架详解(全网最详细!!!)

​​​​​​​ 引言 第一部分&#xff1a;XXL-JOB概述 第二部分&#xff1a;架构与组件 第三部分&#xff1a;使用教程 第四部分&#xff1a;源码分析 第五部分&#xff1a;最佳实践 引言 在分布式系统中&#xff0c;任务调度是一项基础而又关键的服务&#xff0c;它涉…

Java设计模式:享元模式实现高效对象共享与内存优化(十一)

码到三十五 &#xff1a; 个人主页 目录 一、引言二、享元设计模式的概念1. 对象状态的划分2. 共享机制 三、享元设计模式的组成四、享元设计模式的工作原理五、享元模式的使用六、享元设计模式的优点和适用场景结语 [参见]&#xff1a; Java设计模式&#xff1a;核心概述&…

解决Spring BeanCreationException的常见问题

解决Spring BeanCreationException的常见问题 在使用Spring框架进行开发时&#xff0c;可能会遇到各种异常&#xff0c;其中之一就是BeanCreationException。本文将介绍如何解决以下特定的异常&#xff1a; org.springframework.beans.factory.BeanCreationException: Error …

拼接字符串

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 使用“”运算符可完成对多个字符串的拼接&#xff0c;“”运算符可以连接多个字符串并产生一个字符串对象。 例如&#xff0c;定义两个字符串&#…

任务3.1:采用面向对象方式求三角形面积

面向对象编程&#xff08;OOP&#xff09;是一种将现实世界中的实体抽象为对象&#xff0c;并通过类和对象来模拟现实世界中的行为和属性的编程范式。在本实战任务中&#xff0c;我们通过创建一个Triangle类来模拟现实世界中的三角形&#xff0c;并使用面向对象的方法来求解三角…

「清新题精讲」CF249D - Donkey and Stars

更好的阅读体验 CF249D - Donkey and Stars Description 给定 n n n 个点 ( x i , y i ) (x_i,y_i) (xi​,yi​) 和 a , b , c , d a,b,c,d a,b,c,d&#xff0c;求出最多有多少个点依次连接而成的折线上线段的斜率在 ( a b , c d ) (\frac{a}{b},\frac{c}{d}) (ba​,dc​…

linux怎么查询远程管理卡型号

在Linux中&#xff0c;要查询远程管理卡&#xff08;通常是服务器主板上的集成芯片&#xff0c;如iDRAC、iLO、BMC等&#xff09;的型号&#xff0c;可以使用一些特定厂商的工具&#xff0c;或者通过IPMI&#xff08;Intelligent Platform Management Interface&#xff09;来实…

【智能算法】波搜索算法(WSA)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献5.代码获取 1.背景 2024年&#xff0c;H Zhang受到雷达技术启发&#xff0c;提出了波搜索算法&#xff08;Wave Search Algorithm, WSA&#xff09;。 2.算法原理 2.1算法思想 WSA模拟雷达工作时的发射、反…

opencascade 笔记

opencascade 画一个无限大的面 在 OpenCascade 中&#xff0c;要绘制一个无限大的面&#xff0c;你可以使用 gp_Pln 类来定义一个平面&#xff0c;然后将其绘制出来。这里是一个示例代码&#xff0c;演示如何在 OpenCascade 中绘制一个无限大的平面&#xff1a; #include <…

学生管理系统 面向过程

#学生管理系统 面向过程 学生管理系统 面向过程 学生信息:name,tel 1.添加学生 2.删除学生 3.修改学生 4.查询学生 5.查询所有学生 6.退出系统 # 定义一个空列表 stu_list []# help 展示不同的功能 def helplist():print(欢迎使用学生管理信息)print(1.添加学生)print(2.删除学…