C++ primer 要点笔记

232 阅读7分钟

第2章:变量和基本数据类型

2.1 基本内置数据类型

C++的内置数据类型包括了算数类型空类型

2.1.1 算术类型

算数数据有两类:

  • 整形(这里面包括了字符型(char)和布尔类型(T or F))
  • 浮点型(单精度float,双精度double)

其中char占一个字节,int占四个字节

注意:当使用浮点数运算时一般用double,因为float通常精度不够,而两者实际的计算代价相差无几

2.1.2 类型转换

当我们将两种不同的数据类型进行运算时,程序会自动的进行类型转换

这种类型转换被称为强制类型转换

QQ截图20220221212915.png

2.1.3 字面值常量

字面值常量的形式和值决定了它的数据类型,我们可以通过它一眼看出值的类型

比如:看到42就知道整形,4.2是浮点型

字符和字符串字面值

字符型的字面值则是由单引号括起来,如 'a'

字符串的字面值则是由双引号括起来,如 "abcd"

注意

  • 字符串实际上是由常量字符构成的数组
  • 编译器会在字符串的结尾添加一个空字符('\0'),因此字符串的实际长度要比所含字符多一个长度

如:(字符串) "A" ,实际上所占两个字符,分别为本身的字符 'A' 和编译器添加的 '\0'

而字符 'A' ,实际上所占就是本身一个字符

image.png

2.2 变量

变量的本质是一个拥有名字,可以操作存储空间

可以将变量理解为一排 ”保险柜“ ,变量存储空间的大小就相当于 ”保险柜“的大小不同的数据类型的变量就相当于不同种类的”保险柜“

而对象则更像是一种特殊的变量,因为对象的定义就是具有某种数据类型的内存空间

2.2.1 变量定义

定义与声明的区别

定义语法:数据类型 变量名

声明语法:extern 数据类型 变量名

在C++中定义与声明是有所区别

  • 定义变量时,系统会开辟一块存储空间,然后还有一串16进制的数字来表示空间地址,我们就通过变量名代替这串数字来访问这块空间。

    可以简单理解为 我们新开了一个 ”保险柜“ ,并有着与其相对于号码牌的钥匙。而变量名就是这个带编号的钥匙

  • 声明变量时,系统并不会开辟新空间,而是告诉编译器,这个变量已经存在了,接下来可以直接使用

声明变量并不是新开一个”保险柜“,而是提醒编译器,在之前已经有一个一样的”保险柜“了

声明的作用,为了实现多个文件中的代码共享,仅定义一次变量后,可以通过多次声明在不同的文件中使用

所以,我们在声明变量的时候不会为其显示初始化,因为这样就变成了定义,而失去了声明原本的意义

初始值

定义变量的时候获得一个特定值,它就被初始化

  • 初始化的值不一定要求数值型,也可以是任意复杂的表达式

  • 如果我们不显式的给出初始值内置的数据类型变量会根据定义的位置决定

    • 定义在函数外的变量都会被初始化为0
    • 定义在函数内则不初始化

如:double price=109.99,discount=price*0.16

初始化和赋值的区别

在C++中,初始化和赋值是两种不同的操作

int a=1; //定义变量的时候得到了一个初值1,这是初始化

int b;//根据位置,可能初始化,也可能不初始化

b=2;//擦去原有的值,用2代替,这就是赋值

  • 初始化是在创建变量时给其一个初始值
  • 赋值是把当前变量的值擦除,而用一个新值代替

2.2.2 标识符

C++标识符由字母,数字以及下划线组成,其中必须以字母或下划线开头

不能使用关键字作为标识符

2.3 复合类型

基于其他类型定义的类型,指针和引用就是复合类型。

2.3.1 引用

引用是为变量起另一个名字

当我们把变量当成一个 ”保险柜“变量名就是 ”带编号的钥匙“ ,而定义引用就相当于给 “保险柜” 再设置一个备用钥匙

语法

int a=10;

int &A=a; //A是a的另一个名字

int &A; //错误,引用必须初始化

  • 为引用赋值,实际上是把值赋给了与引用绑定的对象

这里的意思是,我们通过备用钥匙来操作"保险柜"的存取等功能,实际对象还是原本的”保险柜“

定义:

大部分引用数据类型要和所绑定的变量严格匹配,并且只能绑定在变量上,不能绑定字面量等。

注意

  • 当我们定义引用时,引用的初始值就与变量绑定在一起,就不能将引用重新绑定在其他变量上。

就是说,当我们给一个 "保险柜" 设置 "备用钥匙" 之后,这个 "备用钥匙" 就不能再开其他柜子了

  • 引用定义时就必须为其初始化

我们在配置备用钥匙的时候,必须要有原本的钥匙才行

  • 强调:引用并非变量,而是将已有的变量起另外一个名字

引用只是备用钥匙,而不是柜子

2.3.2 指针

指针本身就是一个变量,存放的其他变量的地址,允许对指针赋值拷贝,可以先后指向不同变量。

所以指针本身也是一个小柜子,只不过里面只存放“钥匙”

获取对象地址

指针存放着某个变量的地址,使用取地址符& )获取地址。

语法

int a=10;

int *p;

int *p=&a;

上述这段话的意思,可以将其理解为, “将a柜子的钥匙,放到p柜子里”

注意

  • 大部分指针类型要和它指向的变量类型严格匹配

指针值

指针的值(地址)应属于下列4种状态

  1. 指向一个对象(放着柜子的钥匙)
  2. 指向紧邻对象所占空间的下一个位置(放着不知道哪的钥匙)
  3. 空指针(没钥匙)
  4. 无效指针,上述之外的情况

注意:

  • 尽管2,3种形式的指针有效,但它们并没有指向任何具体对象,所以此类指针不能被访问

利用指针访问对象

如果指针指向了一个对象,则运行用解引用符( * )来访问该对象

int a=42;

int *p=&a;

cout<<*p //输出 42

注意

& 和 * 的多重含义

int i=10;

  • 如果 & 跟着类型名出现,是引用 int &r=i;
  • 如果 * 跟着类型名出现,是指针 int *p;
  • 如果 & 出现在表达式中,就是取地址符 p=&i;
  • 如果 * 出现在表达式中,就是解引用符 *p=i;

解引用仅适用于确实指向某个对象的有效指针

空指针

空指针不指向任何对象,在试图使用一个指针代码之前,先检查其是否为空

int *p1=nullptr;    //等价于int *p1=0;
int *p2=0;
int *p3=NULL;       //等价于int *p1=0;

注意:初始化所有指针

如果使用了未初始化的指针,则它当前所占内存空间将被看作一个地址值,去访问一个本不存在的对象

赋值和指针

  • 赋值永远改变的是等号左侧的对象
  • 指针里面只能存放地址
int a=10;
//int *p=a; //错误 指针里面只能存放地址
int *p=&a;  //正确,指针p的初始值改变,现在指向a的地址
*p=20;  //正确, 指针p解引用,实际改变a的值

2.3.3 理解复合类型的声明

指向指针的指针

通过 ***** 的个数,可以区分指针的级别, ****** 表示指向指针的指针

就是将 “钥匙” 到第一个指针内,然后将第一个指针的 “钥匙” 放到第二个指针内

int a=10;
int *pi=&a; //将a的钥匙放入p内
int **ppi=&pi   //将pi的钥匙放入ppi内

\

2月22日更新