C++基础(1)
C++基础(2)
C++基础(3)
目录
1.简介
- 大多数编程语言通过两种方式来进一步补充其基本特征:
- 一是赋予程序员自定义数据类型的权利,从而实现对语言的扩展。(c语言中的结构体,C++中的类等)
- 二是将一些已有的功能封装成库函数提供给程序员。
- 一条表达式是否合法依赖于参与运算的对象类型。C++是一种静态数据类型语言,它的类型检查发生在编译时,因此编译器必须知道程序中每一个变量对应的数据类型。
- C++提供了一组内置数据类型,与内置类型不同,程序员可以自己定义数据类型,为了与C++程序员的内置类型区别开来,通常称为”类类型“。
2. 基本类型
数据类型是程序的基础,他告诉我们是数据的意义以及能在数据上执行的操作。
2.1 基本内置类型
2.1.1 算术类型
- 算术类型分为两类整型(包括字符和布尔类型)和浮点型。
- 不同的机器上算术类型的尺寸有所区别,就是所占的空间。见下表
- 内置类型的机器实现
- 以比特序列存储数据。以2的次幂比特来处理内存,可寻址的最小内存为”字节“。存储的基本单元称为"字"。
- 总结:类型选择:
- 明确知道不可能为负数的时候,选用无符号的。
- 在算术表达中不要使用char和bool,只在存放字符或者布尔值时,才使用他们。因为char在有的机器上是有符号的,有的机器上是无符号的。
- 执行浮点运算选择double,这是因为float不但不够精确,而且运算速度没有double快。
类型 | 最小尺寸 |
char | 8位 |
short | 16位 |
long | 32 |
long long | 64位 |
float | 6位有效数字 |
double | 10位有效数字 |
long double | 10位有效数字 |
2.1.2 类型转换
- 类型所能表示的值的范围决定了转换的过程:
- 非布尔类型算术值赋值给布尔类型时,非0非true,0为false。反过来,布尔类型赋值给非布尔类型时,false的为0,true为1.
- 当赋值给无符号类型一个超出它表示范围的值时,结果是初始值对无符号类型表示数值总数取模后的余数。
- 当赋值给带符号类型一个超出它表示范围的值时,结果是无定义的,此时,程序可能继续工作、可能崩溃、也可能生成垃圾数据。
- 含有无符号的类型的表达式
- 如果是既有有符号,又有无符号,则先把有符号转为无符号,再计算。
- 当无符号数中减去一个值时,不管这个值是不是无符号数,必须确保结果不能是一个负值。
- 切勿混用带符号类型和无符号类型。
2.1.3 字面值常量
1.转义序列
有两种字符不能直接使用,一类是不可打印的字符,如退格或其他控制字符,因为他们没有可视化的图符。另一类是特殊含义的字符(单引号、双引号、问号、反斜线),在这些情况下需要使用转义序列。
3. 变量
- 初始化不是赋值,初始化的含义是创建变量时赋予一个初始值。
3.1 变量声明与定义
- 声音在变量前面加上extern,且声明不占空间。
- 如果声明有extern int i=0;赋值则将不再是声明,有可能还会报错。
- 变量只能被定义一次,但可以被声明多次。
4. 复合类型
这个和声明类似。
4.1引用
引用是为了给对象起另外一个名字。
一般在初始化时,初始值会被赋值(拷贝)到新建的对象中。然而定义引用时,程序把引用和他的初始值绑定在一起,而不是将初始值赋值给它。一旦初始化完成,引用将和它的初始对象绑定在一起,无法令引用绑定到另外一个对象。
4.2 指针
指针与引用的不同点:
- 指针本身就是一个对象,允许对指针赋值和拷贝。
- 指针可以在生命周期内他可以先后指向几个不同的对象。
- 指针无须再定义时赋初始值。
5.const 限定符
默认情况下,const对象仅在文件内有效,想要在其他文件中使用,extern const int butSize=10; 在.h中进行extern const int butSize 声明就好。要加上extern const
5.1 const 引用
把引用绑定到const对像上,就像绑定到其他对象上一样,称为对常量的引用。
const引用称为对常量的引用。与普通引用不同的是,对常量的引用不能被用作修饰它所绑定的对象。
- 对常量的引用,要用const: const int ci=1024; const int &r1=ci;
- r1=42; int &r2=ci;//这两句话都是有问题的,因为r1是对常量的引用,所以不能修改,r2不能让一个非常量引用指向一个常量对象。
5.1.1 初始化和对const的引用
- 引用的类型必须与其所引用对象的类型一致,有两个例外:
- 在初始化常量引用时允许用任意表达式作为初始化,只要该表达式的结果能转换成引用类型即可。
int i = 42;
double dval = 3.14;
const int &r1 = i; //允许将 const int & 绑定到一个普通的int对象上
const int &r2 = 42;
const int &r3 = r1 * 2;
const int &r4 = dval; //这里进行了转换,把daval转换成了 临时量,
int &r5 = r1 * 2;//因为r5不是常量,就允许对r5赋值,会改变r1的值。所以不可以。
5.1.2 指针和const
指向常量的指针不能用于改变其所指对象的值。要想存放常量对象的地址,只能使用指向常量 的指针。
const double pi = 3.14;
double *ptr = *pi;//要用常指针指向pi
const double *ptr = π
*cptr = 42; //不能赋值
- 指针的类型必须与其所指对象的类型一致,但有两个例外:
- 允许令一个指向常量的指针指向一个非常量的对象。
- const 指针:
- 常量指针必须初始化,一旦初始化完成,则它的值就不能在改变了。把*放在const关键字之前用以说明指针是一个常量,这样书写形式隐含着一层意味,即不变的是指针本身的值而非指向的那个值。
int errNumb = 0;
int *const curErr = &errNumb; //
const double pi = 3.14159;
const double *const pip = π
*pip = 2.72;//错误
if (*curErr)
{
*curErr = 0;//可以
}
3. 从右向左看,离curErr最近的符号是const,意味着curErr本身是一个常量对象,对象的类型由
声明符 的其余部分确定。声明符中的下一个符号就是* ,意思是curErr是一个常量指针。最后,
该声明语句的基本数据类型部分确定了常量指针指向的是一个int 对象。
4. 指针本身是一个常量并不意味着不能通过指针修改其所指对象的值,能否这样做,完全依赖于
所指对象类型(总结,就是常量指针指向的对象的值能否修改,要取决于指向对象是不是常量。常
指针不能再指向其他的对象了)。例如上面的pip是一个指向常量的常量指针,则不论是pip所指的
对象值还是pip自己存储的那个地址,都不能改变。但curErr指向的是一个一般的非常量整数,那
么完全可以用curErr去修改errNumb的值。
5.1.3 顶层const
用名词顶层const表示指针本身就是个常量,用底层const表示指针所指的对象是一个常量。
- 顶层const执行拷贝一般没有什么影响。
- 但是底层const当执行拷贝时操作时,拷入和拷出的对象必须具有相同的底层const资格,或者两个对象的数据类型必须能够转换。
int i = 0;
int *const p1 = &i; //顶层,不能改变p1的值
const int ci = 42; //顶层 不能改变ci的值
const int *p2 = &ci;//这是个底层,可以改变p2的值
const int *const p3 = p2; //靠右的const是顶层,靠左的是底层
const int &r = ci; //用于声明引用的const 都是底层const
int *p = p3; //错误,p3是底层const,而p没有
5.1.4 常量表达式
常量表达式是指不会改变并且在编译过程就能得到计算结果的表达式。显然字面值属于常量表达式,
const int limita = 27;//是常量表达式
const int sz = get_size();//不是常量表达式,因为要在运行的时候,才有结果。
5.1.4.1 constexpr变量
待补充。。。。
5.1.4.2 字面值常量
待补充。。。。
5.1.4.3 指针和constexpr
待补充。。。。
20181205