变量和基本类型
变量定义
类型说明符 变量名 = 初始值
注意:初始化和赋值的区别
初始化:创建变量的时候赋予其一个初始值
赋值:把对象的当前值擦除,用新值来替代
初始化
-
列表初始化
例如:①int i = 0; ②int i(0) ③int i{0}
② 如果用变量来初始化,可能会丢失精度,但可以初始化成功
③ 是 C++11 的特性,如果会丢失精度,编译器会报错,初始化失败void test() { int i(3.14); cout << i << endl; //3 int j{3.14}; //编译错误 }
-
默认初始化
定义在任何函数体之外的变量被初始化为 0
定义在函数体内部的内置类型变量将不被初始化(依据书中,但不同编译器做法不同)
类可以自主决定初始化对象的方式(构造)
建议初始化每一个内置类型的变量
声明与定义
声明:规定变量的类型和名,不会默认初始化,而是未定义
定义:除声明所做事情之外,还会创建与名字关联的实体
extern int i; //声明
int j; //定义
extern int k = 2; //定义(显示初始化的声明会成为定义,函数体内部不能用)
变量只能被定义一次,但可以声明多次(定义出现在某一个文件中,其他文件只能对其进行声明)
引用和指针
-
引用
引用始终和它的初始值(只能是对象)绑定在一起(之后无法改变),因此 定义引用的时候必须初始化且不能是例如字面值之类的非对象初始值操作引用实际上就是在操作与之绑定的对象
void test() { int &ref1; //错误,未初始化 int &ref2 = 1024; //错误,绑定的不是对象,而是字面值 int value = 1024; int &ref3 = value; ref3 = 2048; cout << value << endl; // 2048,引用就是被绑定对象的别名 cout << ref3 << endl; // 2048 }
引用本身不是一个对象,因此不能定义引用的引用
引用类型要与初始化对象类型对应 -
指针
指针保存对象的地址,同时指针本身也是一个对象,可以重复赋值,也可以被引用绑定
获取一个对象的地址使用&
,用对应类型的指针接收
有效的指针通过解引用*p
来访问指向的对象空指针,
int *p = nullptr;
建议初始化所有指针,不然不知道指向了那一块内存,使用时可能会出现访存错误
void*
指针,只是单纯存放一个内存地址,由于不知道此地址存放的对象的类型,可以进行的操作有限 -
对指针的引用
int *&pi = p;
从右往左阅读,首先&pi
是一个引用,对int *
的引用,也就是对指针的引用
const
限定符
作用:不允许const
修饰的对象重新赋值
-
初始化
const
对象一旦创建后其值不能再改变,因此必须进行初始化
可以用其他对象对const
对象进行初始化,也可以用const
对象初始化其他对象(调用 operator=)void test() { int i = 10; const int j = i; // j的常量特性只在执行改变j时发挥作用 int k = j; //合理,k拷贝j的值并不会改变j }
-
extern 的利用
const int buffSize = 512;
,编译器在编译的时候将所有buffSize
替换为 512
const
对象被设定为只在文件内有效//file_1.cpp extern const int buffSize = func(); //extern限定使常量能被其他文件所用 //file_1.h extern const int buffSize; //在头文件表明const对象文件共享
多个文件共享
const
对象需要在const
对象的定义前加 extern -
常量引用
const int a = 1024; const int &ref = a;
引用的对象不可变,由于引用是别名(改变引用会改变绑定的对象),所以引用也不能变。
-
常量引用的初始化
与一般的引用不同,常量引用可以用非常量引用的对象、字面值来初始化double val = 3.14; const int &ref = val; //实际上发生 const int temp = val; //引用类型的临时量接受原类型的转换值 const int &ref = temp; //对临时量进行常量引用
举个栗子
常量引用相当于给自己强制加了不可更改的道德准则,对于任何其他道德准则它都可以进行综合阉割并接收=》对应于初始化
其他人可以复印它的道德准则,因为这样没有更改原件的风险=》对应于普通变量接收常量
但是其他人要它的原件,它的道德准则就有被其他人修改的风险=》对应于普通引用接收常量void test() { int i = 10; const int &ref1 = i; // 正确,i没道德无所谓,ref1有就行 int k = ref1; // 正确,k只复印ref1的准则 int &m = ref1; // 错误,m要ref1的准则原件 }
-
指针和
const
指向常量的指针(存放常量对象的地址),称为底层const
(解引用的对象不可修改)
const
指针(指针变量的值不能改变),称为顶层const
(指针本身不可修改)指向常量的指针或者引用,仅仅规定不能通过指针或者引用来改变对象,但对象到底能不能改变不由他俩决定,也就是上述例子说的它们只在乎自己的道德准则
处理类型
-
类型别名
关键字:typedef
typedef double wages, *p;
,wages 是 double 的同义词,p 是double*
的同义词
别名声明:using
using SI = Sales_item;
,SI 是 Sales_item 的同义词 -
指代复合类型
typedef char* pstring; const pstring p = nullptr;//p是指向char的常量指针(把pstring看成基本类型,顶层const,p不可变),还原为const char *p = nullptr;认识是底层const是错误的
当复合类型使用了别名,使用别名时就相当于在使用基本类型
-
auto 类型说明符
作用:对于事先不知道的数据类型,auto 让编译器通过初始值来推算变量的类型 -
decltype
类型指示符
decltype(func()) sum = 100;
,sum 的类型就是func()
的返回值类型 -
编写头文件
类通常被定义在头文件中,文件名与类名一致
预处理器(编译之前的一段程序)技术可以解决头文件多次包含的问题-
预处理功能#include
预处理器看到#include 标记时,会用指定的头文件内容替代#include -
头文件保护符
#define 指令设定预处理变量,#ifdef
和#ifndef
检查预处理变量是否定义,直到#endif
指令结束
建议使用防卫式声明#ifndef __HEAD_H__ #define __HEAD_H__ ... #endif
-