Primer C++第二章学习笔记

在这里插入图片描述
数据类型决定了程序中数据和操作的意义

2.1 基本内置类型

2.1.1 算术类型

C++定义了一套包括算术类型和空类型在内的基本数据类型,其中包含了字符、整型数、布尔值和浮点数。空类型应用与一些特殊的场景。
在这里插入图片描述
在这里插入图片描述
类型决定了数据所占的比特数以及该如何解释这些比特的内容。

带符号类型和无符号类型
在这里插入图片描述
在这里插入图片描述
类型int、long、long long所占用的比特数不一样,它们占用的比特数分别是16位、32位、64位。无符号类型所有比特都用来存储值,有符号类型的有一个比特数用于表示符号位,剩余的比特数存储值,有符号类型表示范围内正值和负值的量应该平衡。float和double占用的比特数不同。

在这里插入图片描述
利率可以是小数,选择浮点型,根据贷款的最大额度可以相应地选择float或者double,本金一般是整数,选择整型,根据最大本金可以相应选择int、long或long long;付款是包含本金和利率的,因此可能是小数,选择浮点型,根据最大额度可以相应地选择float或者double。

正确答案:选择double,浮点型可以表示实数,而且计算代价稍微大于float但是表示的范围更广。

2.1.2 类型转换

类型转换是被大多数类型支持的运算

我们来看看类型转换过程中到底发生了什么?
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
注意:-1 / 256 = -1 … 255

避免无法预知和依赖于实现环境的行为

含有无符号类型的表达式
当一个算术表达式中既有无符号又有int值时,那个int值就会转化成无符号数。
在这里插入图片描述
把负数转成无符号数类似于直接给无符号数赋一个负数,结果等于这个负数加上无符号数的模
最后一行的u+i= -42 + 2^32 + 10 = 4294967264

无符号数不会小于0这一事实同样关系到循环的写法。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
答:32,
4294967264, u - u2可以正确计算,直接结果是-32,所以在表示无符号整数时自动加上了模,在int占32的情况下,结果为-32 + 2^32 = 4294967264,
32,
32,
-32,
0,
0
在这里插入图片描述
同一个表达式中混用无符号类型和有符号类型,在计算前有符号类型会自动转换成无符号类型,当带符号类型取值为负时就会出现异常,取值为正时不会出现异常
在这里插入图片描述
在这里插入图片描述

2.1.3 字面值常量

各种进制的数
在这里插入图片描述
十进制面值类型是int、long、long long中尺寸最小的那个。八进制和十六进制字面值类型是能容纳其数值的int、unsigned int、long、unsigned long、long long和unsigned long long中尺寸最小者。

默认情况下,浮点字面值是一个double

字符和字符串字面值
在这里插入图片描述
编译器在每个字符串的结尾处添加一个空字符(’\0’);
如果两个字符串面值位置紧邻且仅由空格、缩进和换行符,则实际上它们是一个整体。
在这里插入图片描述

转义字符

有两类字符是程序员不能打印的:

  • 不可打印字符(退格或者其他控制字符)
  • 特殊含义字符(单引号,双引号,问号和反斜线)
    在这里插入图片描述
    在程序中,上述转义字符被当做一个字符使用。
    泛化的转义字符\x后紧跟一个或多个16进制数字
    在这里插入图片描述
    \后面跟着的八进制数字不超过3个,\x要用到后面跟着的所有数字。

指定字面值类型
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
答:(a) char, wchat_t,char*, wchat_t*,字面值:字符a, 宽字符型字面值a,字符串a,宽字符型字符串a
(b)int, unsigned int, long, unsigned long, 整型八进制,整型十六进制,字面值:10,无符号整数类型的10,长整数存储的10,无符号长整数存储的10,八进制int整型值为10,十六进制int面值为12
© double, float, long double,字面值:面值相同,存储类型不同
(d)int, unsigned int, double, double,字面值分别是10,10,10.,0.1

在这里插入图片描述
答:有区别,第一行数字是十进制的,定义了十进制数9和7;第二行定义是错误的,因为0开头的数是八进制的数,而数字9超出了八进制的表示范围,编译无法通过。

在这里插入图片描述
答:(a)表示的是一个字符串,里面用到了转义字符,其中\145表示字符e,\012表示一个换行符,因此输出结果为:"Who goes with Fergus?
"(b)是用long double存储的浮点数,并且用到了科学计数法,它表示的值是31.4;© 将出现编译错误的问题,因为1024是整型的字面值,但是后面加入f表示用float浮点型存储,会出现矛盾,应该改为1024.f(d) 表示用long double存储的浮点数,字面值是3.14

在这里插入图片描述
在这里插入图片描述

2.2 变量

变量提供一个具名的、可供程序操作的存储空间,C++中每个变量都有其数据类型,数据类型决定着变量所占空间的大小和布局方式,该空间的存储值的范围、以及变量能参与的运算。

2.2.1 变量定义

对象是指一块能存储数据并具有某种类型的内存空间

初始化不是赋值,初始化的含义是创建变量时赋予其一个初始值,而赋值的含义是把对象的当前值擦除,而以一个新值来代替

定义于函数体内的内置类型的对象如果没有初始化,则其值未定义。类的对象如果没有显式地初始化,则其值由类确定。

在这里插入图片描述
答:(a) 错误,应该先定义变量,在进行输入操作,改为:int input_value; std::cin >> input_value;
(b)引发警告,用初始化列表的方式将浮点型给int类型变量初始化会报错,应该用float或double等浮点类型的变量来存储; double i = {3.14};
(c)错误,初始化不可以连续加等号,应该改为 double salary = 9999.99, wage = 9999.99;
或者改为 double salary, wage; salary = wages = 9999.99;
(d) 引发警告,但是一般不推荐将浮点数给int类型变量初始化。

在这里插入图片描述
答:global_str初值为"", global_int初值为0,local_int在main函数内部,将不被初始化,local_str初值为""。

对于string类型的变量来说,因为string类型本身接受无参数的初始化方式,因此无论变量定义在函数内还是函数外都被默认初始化为空串。

建议初始化每一个内置类型的变量。虽然并非必须这么做,但如果我们不能确保初始化后程序安全,那么这么做不失为一种简单可靠的方法。

2.2.2 变量声明和定义的关系

声明使得名字为程序所知,一个文件如果想使用别处定义的名字则必须包含对那个名字的声明。而定义负责创建与名字关联的实体。

在这里插入图片描述

变量能且只能被定义一次,但是可以被多次声明。

在这里插入图片描述
答:(a)定义,(b)定义,(c)声明

C++是一种静态类型语言,其含义是在编译阶段检查类型。在C++中,编译器负责检查数据类型是否支持要执行的运算,如果试图执行类型不支持的运算,编译器将报错。程序越复杂,静态类型检查越有助于发现问题,但是这要求我们在使用某个变量之前必须声明其类型。

2.2.3 标识符

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
答:(a)非法,double是保留关键字不可以用作变量名;(b)正确;(c)错误,变量名中不可以出现“-”(d)错误,标识符必须以字母或下划线开头,不能以数字开头(e)正确

2.2.4 名字的作用域

作用域是程序的一部分,在其中名字有其特定的含义。C++中大多数作用域都以花括号分隔。

建议:当你第一次使用变量时再定义它

在这里插入图片描述

如果函数有可能用到全局变量,则不宜再定义一个同名的局部变量。
在这里插入图片描述
答:100
在这里插入图片描述
答:合法,将输出100 45

2.3 复合类型

复合类型是指基于其他类型定义的类型,C++有几种复合类型,本章将介绍引用和指针

一条声明语句由一个基本数据类型和紧随其后的一个声明符列表组成

2.3.1 引用

引用为对象起了另外一个名字,因为定义引用时程序把引用和它的初始值绑在一起,而不是将初始值拷贝给引用,因为无法令引用重新绑定另外一个对象,因此应用必须初始化

在这里插入图片描述
答:(b)是不合法的,因为引用不能和字面值绑定;(d)是不合法的,定义引用时必须进行初始化。

在这里插入图片描述
答: (a)是合法的,它让d中的值变成了3.14159,(b)是合法的,它让d中的值变成了0,©是合法的,但因为d是双精度浮点数而i是整数,所以该语句实际上执行了窄化操作,(d)是合法的,原因同©

在这里插入图片描述
答:10 10

2.3.2 指针

指针是指向另外一种类型的复合类型。与引用类似,指针也实现了对其他对象的间接访问。然而指针与引用相比又有很多不同点。其一,指针本身就是一个对象,允许对指针赋值和拷贝,而且在指针的生命周期内它可以先后指向几个不同的对象。其二,指针无须在定义时赋初值。和其他类型一样,在块作用域内定义的指针如果没有初始化,也将拥有一个不确定的值。

指针存放某个对象的地址,要想获取该地址,需要用取地址符&

在声明语句中指针的类型实际上被用于指定它所指对象的类型,所有二者必须匹配,否则会发生错误

指针值应属于4中状态之一:

  1. 指向一个对象
  2. 指向紧邻对象所占空间的下一个位置
  3. 空指针
  4. 无效指针

尽管第2种和第3种形式的指针是有效的,但其使用同样受到限制。

如果指针指向了一个对象,则允许使用解引用符*来访问该对象,但解引用操作仅适用于那些确实指向了某个对象的有效指针

在这里插入图片描述

空指针
在这里插入图片描述

建议初始化所有指针

void是一种特殊的指针类型,可用于存放任意对象的地址。利用void指针能做的事情比较有限,可以拿它和别的指针比较、作为函数输入输出、或者赋值给另外一个void*指针。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
答:1、指针本身是一个对象,允许对指针赋值和拷贝,而且在指针的生命周期内它可以先后指向几个不同的对象,引用不是一个对象,无法令其重新绑定到另外一个对象2、指针无须在定义时赋值。

在这里插入图片描述
答:令i的值变成自身的平方。

在这里插入图片描述
答: (a) 非法,指针类型和指向的对象类型不一致;(b) 非法,给指针赋0不可以用变量赋值;© 合法

在这里插入图片描述
答:第一行含义是如果p不是空指针,则执行以下命令;第二行的含义是如果p指向的对象不是0,则执行以下命令

在这里插入图片描述
答:在有初始化指针的情况下,判断p是否指向合法的对象,只需把p作为if语句的条件即可;如果没有初始化就比较麻烦,一种处理方式是把if§置于try结构中,当程序块顺利执行时,表示p指向了合法的对象;当程序出错转到catch语句时,表示p没有指向合法的对象。

在这里插入图片描述
答:void*指针可以指向任意类型的对象,因此p合法,long *指针只能指向long类型的对象,而i是int类型对象,因此lp不合法

2.3.3 理解复合类型的声明

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

指向指针的指针

引用本身不是一个对象,因此不能定义指向引用的指针。但是指针是对象,所有存在对指针的引用

面对一条比较复杂的指针或者引用的声明语句时,从右向左有助于弄清楚它的真实含义

在这里插入图片描述
答:(a) ip是int类型指针,i是int类型对象,r是int对象i的引用;(b) i是int类型对象,ip是int类型指针,它的值是0© ip是int类型指针,ip2是int类型对象

2.4 const限定符

有时我们希望定义这样一种变量,它的值不能被改变,为了满足这一要求,可以用关键字const对变量的类型加以限定

因为const对象一旦创建后其值就不能再改变,所以const对象必须初始化

默认状态下,const对象仅在文件内有效

如果想在多个文件之间共享const对象,必须在变量的定义之前添加extern关键字

在这里插入图片描述
答:(a)不合法,const的对象必须进行初始化;(b) 合法;© 合法;(d) 不合法,sz是const对象,它的值不能改变

2.4.1 const的引用

可以把引用绑定到const对象上,就像绑定到其他对象上一样,我们称为对常量的引用

引用的类型必须与其引用对象的类型一致,但是有两个例外。第一种例外就是在初始化常量引用时允许用任意表达式作为初始值,只有该表达式结果能转换成引用的类型即可。

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

2.4.2 指针和const

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

指针的类型必须与其所指对象的类型一致,但是有两个例外。第一种例外情况是允许令一个指向常量的指针指向一个非常量对象

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

const指针,指针是对象,允许把指针本身定为常量,常量指针必须初始化,而且一旦初始化完成,则它的值,也就是存放在指针的地址就不能改变了。

在这里插入图片描述
答:(1) 不合法,非常量引用不可以引用一个字面值常量,(b) 合法,这样意味着p2只能指向i2;(c)正确,这里说明i是一个常量,r是常量引用;(d)正确,这说明p3只能指向i2,同时不能通过p3改变i2的值;(e)正确,这说明不能通过p1改变i2的值,但可以让p1指向另外的对象;(f)错误,引用本身不是对象,因此不能让引用恒定不变
(g)正确,这样i2是一个常量,r是常量-1的引用

在这里插入图片描述
答:(a) 不合法,cp是一个常量指针,因为其值不能改变,所以必须初始化(b)非法,因为p2是常量指针,因为其值不能被改变,所有必须初始化(c)非法,ic是一个常量,所有必须进行初始化(d)非法,p3是常量指针,必须进行初始化(e)是合法的,但是p没有指向任何实际的对象

在这里插入图片描述
答:(a)合法,(b)不合法,普通指针指向一个常量,从语法上说p1的值可以随意改变,显然是不合理的,(c)不合法,因为ic是一个常量,因此应该用无法更改指向对象的值的指针才可以指向(d)非法,p3是常量指针,不可以更改指向(e)非法,p2是常量指针,不可以更改指向(f)非法,ic是常量,不可以更改常量的值

2.4.3 顶层const

用名词顶层const表示指针本身是个常量,而用底层const表示指针指的对象是一个常量;顶层const表示任意的对象是常量,而底层const与指针和引用等复合类型的基本类型有关

当这行对象的拷贝操作时,常量是顶层const还是底层const区别明显,其中顶层const不受影响,底层const的限制却不能忽视。当执行对象的拷贝操作时,拷入和拷出的对象必须具有相同的底层const资格,或者两个对象的数据类型可以转换。一般来说,非常量可以转成常量,反之则不行

用于声明引用的const都是底层const

在这里插入图片描述
答:p2,r2被声明了底层const,v2,p3被声明了顶层const

在这里插入图片描述
答:r1 = v2合法,r1是非常量引用,v2是一个常量(顶层const),把v2的值拷贝给r1不会对v2有任何影响; p1 = p2; 不合法,p2是底层const,p1是普通指针,不可以将底层const赋值给普通指针;p2 = p1; 合法,p2可以指向非常量,只不过我们不会通过p2更改它所指的值;p1 = p3; 不合法,p3包含了底层const定义,不能把p3的值赋给普通指针;p2 = p3; 合法,p2是底层const,p3也包含了底层const

2.4.4 constexpr和常量表达式

常量表达式是指值不会改变并且在编译过程中就能得到计算结果的表达式
C++ 11新标准规定,允许将变量声明为constexpr类型以便由编译器来验证变量的值是否是一个常量表达式。声明为constexpr的变量一定是一个常量,而且必须用常量表达式初始化。
声明constexpr时用到的类型是“字面值类型”,包括算术类型,引用和指针,不包括自定义类,IO库、string类型;尽管指针和引用都能定义成constexpr,但是它的初始值只能是nullptr或者0,或者是存储于某个固定地址的对象。
在constexpr如果声明了如果定义了一个指针,限定符constexpr仅对指针有效,与指针所指的对象无关

在这里插入图片描述
答:非法,改为int null = 0, *p = &null;
另外一种改法是int null = 0; *p = nullptr;

2.5 处理类型

在这里插入图片描述

2.5.1 类型别名

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

2.5.2 auto类型说明符

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
答:a是一个整数,a=42;让整数a的值变成42;b是一个整数,b=42;让整数b的值变成42;c是一个整数,c=42;让整数c的值变成42;d和e都是指针,所以不能用字面值为其赋值;g绑定到整型常量,所以不能修改它的值。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
答:i是整型常量、j是整型变量;k的类型是整型常量;p是指向整型常量的指针;j2的类型是整数;k2的类型是整数

2.5.3 decltype类型指示符

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
答:a的类型是整数、b的类型是整数、c的类型是整数、d的类型是int&,结果a=4,b=4,c=4,d=4

在这里插入图片描述
答:a的类型是int、b的类型是int、c的类型是int、d的类型是int&,a的值是3、b的值是4、c的值是3、d的值是3

在这里插入图片描述
答:int a = 1; decltype(a) b; auto b = a;两者的类型一样;int a = 1; decltype((a)) b; auto b = a;两者的类型不一样。
在这里插入图片描述

2.6 自定义数据结构

从最基本的层面理解,数据结构是把一组相关的数据元素组织起来然后使用它们的策略和方法。

2.6.1 定义Sales_data类型

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.6.2 使用Sales_data类

在这里插入图片描述

2.6.3 编写自己的头文件

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值