一、变量定义
1.列表初始化
例如:
int a=0;
int b{0};
int c={0};
2.变量默认初始化
内置类型的变量,没有显示初始化。如果变量定义在函数之外(包括main()函数),则初始化为0;如果变量定义在函数之内,则不进行初始化。对于自定义的类型,初不初始化,由类具体决定。
二、变量声明与定义
1.声明
声明使得名字为程序所知,声明一个变量要在变量前加extern关键字,并且不能显式地初始化变量。
如:
extern int b;
2.定义
定义负责创建与名字关联的实体。定义申请了存储空间,有时还会显式地初始化变量。任何包含了显式初始化的声明都是定义。
如下都是定义:
extern int a=10;
int a;
int a=10;
3.声明与定义的区别
要在多个文件中使用同一个变量,就必须将定义和声明分开。
变量的定义必须出现且只能出现在一个文件中,其他用到该变量的文件只能声明,绝对不能重复定义。
三、变量命名规范
1.标识符要能体现实际含义
2.变量名一般使用小写字母
3.用户自定义类名一般大写字母开头
4.如果标识符由多个单词组成,则单词应有明显区分
5.作用域:全局作用域
块作用域
内层作用域和外层作用域
如下代码:
int i = 100, sum = 0;
for (int i = 0; i != 10; i++)
sum += i;
std::cout << i <<" " << sum << std::endl;
最后输出是,i=100,sum=45,因为循环中的i和循环外部的i作用域不同,循环内部的i并不会影响更高一级的作用域中的i值
四、引用
引用的就是给变量起了一个别名(个人见解)。
引用必须初始化,并且初始化的类型要一致,只能用对象初始化引用,不能是某个值或计算结果。引用也可以赋值。
如:
int a=10;
int &b=a;//引用声明并且初始化
b=20;//a和b的值都是20
五、指针
1.指针本身就是一个对象,允许赋值拷贝,也允许在生命周期内指向几个不同对象
2.指针定义时无须赋初值,如赋初值,则必须类型相匹配
3.指针值:
指向一个对象的地址
指向紧邻对象所占空间的下一位置(地址)
空指针(不指向任何对象)
无效指针(不属于以上三种情况)
4.取地址操作符&,访问指针对象操作符(解引用符)*
如:
int a=20;
int *pt=&a;//取a地址,赋值给指针pt
int *b;
*b=a;//解引用符
int c=*b;//解引用符
5.引用不是对象,因此不能创建指向引用的指针
6.空指针:指不指向任何对象的指针,实现方法有以下三种:
int *a=0;
int *a=nullptr;
int *a=NULL;
NULL是预处理变量,在头文件cstdib中,预处理变量不属于std命名空间
7.任何非零指针对应的条件值都是true
8.void* 指针:特殊类型的指针,可以存放任意对象的地址
六、复合类型的声明
1.变量的定义包括:一个基本数据类型(base type)和一组声明符
如:int i=1024,*p,&b=i;其中int是基本数据类型,*,&都是声明符
因此,这种写法:int* i,p;和int *i,p;中*只修饰到了i,p任然是int类型
2.指向指针的指针
int **p;
3.指向指针的引用
int a=20;
int *p;
int *&r=p;//r是指向p指针的引用
r=&a;//给r赋值就是将p指针指向了a
4.复杂指针或引用的声明语句
方法是从右向左阅读,依次弄清楚含义
如:
int *&r=p;
要看r是什么类型,先看离r最近的修饰符是&,因此r是引用,再看&r前面的*,所以r是一个指针的引用
七、const限定符
1.const限定的变量不能再更改,定义时必须初始化
2.const限定的变量可以参与一些操作,前提是这些操作不会改变它的值
3.默认状态下const对象仅在文件内部有效,要想在多个文件共享const对象,必须在变量的定义之前添加extern关键字
//file_1.h中定义并初始化了一个变量,添加extern关键字,使得能被其他文件访问
extern const int bufSize=fcn();
//file_1.cc中要使用时,必须添加声明
extern const int bufSize;
4.对常量的引用(reference to const):把引用绑定到const对象上,引用的类型必须与其所引用的对象的类型保持一致,但是允许一个常量引用绑定非常量的对象、字面值、一般表达式
int i=42;
const int ii=42
const int &r1=i;//正确
const int &r2=42;//正确
int &r3=ii;//错误
i=54;//正确,r1和i值都是54
r1=54;//错误
5.指向常量的指针
指向常量的指针,不能用指针改变所指对象的值,因为指针指向的是一个常量。
要想存放常量对象的值,只能用指向常量的指针。
const double p1=3.14;
const double p2=3.14;
double p3=3.14;
const double *ptr=π
ptr=&p2;
ptr=&p3;
指向常量的指针可以改变指向的对象,并且对象是非常量也可以(如上所示)
6.指针常量(const指针)
指针常量是指针本身就是一个常量,因此指针常量的值(所指向的地址)是不能改变的,但是可以通过指针和指向的对象改变对象的值(地址所指的那个值)
int c = 30;
int *const ptr1 = &c;
c = 40;
*ptr1 = 50;
7.对5、6的总结
区别指向常量的指针和指针常量关键是看谁是常量,确保操作过程中常量值不能改变就可以了。指向常量的指针是指针指向了一个常量,并且对常量地址的存放,只能用指向常量的指针;指针常量是指针本身是个常量,即指针(地址)不能改变,而指针(地址)所指向的值是可以改变的。
8.顶层const和底层const(只是一个定义而已)
顶层const:表示指针本身是个常量
底层const:表示指针所指的对象是一个常量
9.constexpr关键字
将变量声明为constexpr类型以便编译器来验证变量的值是否是一个常量表达式,声明为constexpr的变量一定是一个常量,而且必须用常量表达式初始化。如果在constexpr中定义了一个指针,限定符contexpr只对指针起作用,即常量指针。
八、处理类型
1.类型别名:有两种写法typedef和using
如:
typedef double dbe;dbe就代表了double
using double dbe;dbe就代表了double
2.auto类型说明符
auto让编译器通过初始值来推算变量的类型,因此auto定义的变量必须要有初始值。auto一般会忽略顶层const,保留底层const
3.decltype类型指示符
选择并返回操作数的数据类型,这个返回的类型包括顶层const、底层const和引用在内,同时要注意顶层const和引用的初始化
decltype (r+10) b;//r+10的类型传递给b
切记切记:decltype((variable))(注意是双层引号)的结果永远是引用,而decltype(variable)结果只有当variable本身就是一个引用时才是引用