![](https://i-blog.csdnimg.cn/blog_migrate/7ad7a73a3ce0ba002f6962df260b3ac0.png)
本人为刚入门编程语言的新人,对于C++的学习和了解稍显浅显,做这个系列也是记录与学习,若有不妥也请各位大佬可以指出。
该系列的学习分享主要依据C++ Primer 第五版
复合类型
*声明语句:一个基本数据类型和紧随其后的一个声明符列表(每个声明符命名并了一个变量并指定了该变量与基本数据类型有关的某种类型 --->更复杂的类型
引用
*通常我们所指的引用是'左值引用'(左值:一般指出现在等号左边的例如对象),C++11中才新引入了右值引用
引用一般形式:&d(变量名)-->将某个现有的对象和某个值或对象绑定起来(另一个名字)-->必须初始化
int ival = 1024;
int &refVal = ival; //refVal指向ival <-> 相当于另一个名字的ival
int &refVal2; //错误使用:引用必须被初始化!!
*引用仅能和某个对象绑定,而不能和某个表达式或某个字面值绑定在一起
指针(相对重要***)
-->相比于引用:
指针本身是一个对象,允许对指针赋值和拷贝,而且在其生命周期内他可以指向不同的对象
无须赋初值,和其它内置类型一样,在块作用域内没有初始化的化,将得到一个不确定的值
一般形式:*d(变量名)-->指针存放的是某个对象的地址-->how获取地址?-->取地址符(&)
int ival = 1024;
int *p = &ival; //p中存放的是ival的地址,
//或者说p是指向整型对象ival的指针
int *pt = p; //将一个指针赋值给另一个指针
cout << *P; //由符号*得到指针p所指对象,输出1024
//若没有*会输出地址(还未测试!!)
*指针的声明对象要相统一(int 对 int double 对 double)
*建议初始化所有指针,就算没定数,就先赋值一个nullptr或0 <--很多运行问题出现点(访问无效指针或未定义的区域)
*区分’=‘赋值是改变了指针的值还是改变了指针对象的值
int i = 1024;
int *p = &i; //指针的值改变
int *p = 123; //指针所指的对象的值改变
特殊的指针void*指针
可以存放任何对象的地址,但是我们并不知道它所指的对象的类型是什么
-->不能操作void*指针所指的对象
可以和别的指针比较
作为函数的输入输出
赋值给另外一个void*指针
理解复合类型的声明
定义多个变量--> 同一行中间用逗号隔开,或者不同行分别定义
指向指针的指针 -->访问的话就需要两次或多次解引用
int ival = 1024;
int *p = &ival; //p指向一个int型的数
int **pp = &p; //pp指向一个int型的指针
![](https://i-blog.csdnimg.cn/blog_migrate/90d33a7211c8a8dcd3c410630a11a983.png)
指向指针的引用
int i = 42;
int *p;
int *&r = p; //r是一个对指针p的引用
r = &i; //r引用了指针,因此给r赋值就是邻p指向i;
*r = 0; //解引用r得到i,也就是p所指的对象,将i赋值为0
*面对复杂声明变量:最好的阅读方式是从右向左读,谁离的最近谁就对该对象的影响最大;
-->ep: int *&r = p; 那么我们可以把(&r)看成一个整体,他是个引用,再将*加上去,那么就可以
知道r是一个对整型指针p的一个引用;
const限定符
*目的:我们希望有一个值不能被改变,例如缓冲区的大小
基本特征:
可以在基本类型的前面加上const限定符
const后的对象必须要初始化,并且不能通过被初始化的对象来改变该值
const对象,在默认情况下仅在当前文件下有效 -->解决方法:在前面再加一个extern
const的引用:
对常量的引用,不同的是对常量的引用不能被用左修改它所绑定的对象
-->C++其实并不允许随意改变引用所绑定的对象,那么这么看来,所有引用都是常量引用
const int ival = 1024;
const int &p1 = ival; //正确:引用及其对象都是常量
p1 = 42; //错误:p1是对常量的一个引用
int &p2 = p; //错误:试图让一个非常量指针指向一个常量对象
*在对需要进行内置类型转化的常量赋值,我们采用临时量来进行传递,即内部进行两次赋值,并且对应绑定的对象不是所赋的值而是临时量
const和指针
当const和指针混在一起时我们将会有两种类型的名称:
指向常量的指针(所指的对象是常量)
常量指针(指针本身就是常量)
顶层const和底层const
$很自然的从上述const和指针的关系我们需要进一步知道const对类型的影响$
顶层const:指针本身是个常量
底层const:指针所指的对象是一个常量
int i = 0;
int *const p1 = &i; //不能改变p1的值,这是个顶层const
const int ci = 42; //不能改变ci的值,这是个顶层变量
const int *p2 = &ci; //可以改变p2的值,这是一个底层变量
const int *const p3 = p2; //靠右的const是顶层,靠左的是底层
const int &r = ci; //用于声明引用的const都是底层的const
区别:
拷贝操作时,顶层变量无影响,底层变量的限制不能忽视
-->当执行对象拷贝时,拷入和拷出的对象必须具有相同的底层const,或者两者间可以进行转化(一般来说非常量可以转化为常量,反之则不行)
constexpr和常量表达式
定义:常量表达式是指值不会发生改变并且在编译过程中就能得到结果的表达式(表达式不计;)
const int max = 10; //是常量表达式
const int sz = get_size(); //不是常量表达式
*一般语句中对象的具体值若是直到运行时才能确定的不是常量表达式
-->一般来说,若该变量是一个常量表达式,那么用constexpr来代替const
字面值类型
定义:类型简单,值显而易见,称之为字面型常量(包括算术类型、引用和指针)
*指针和引用定义成constexpr时,必须初始化值为0或nullptr
constexpr声明符中定义了变量,那么constexpr仅对指针有效,与指针所指的对象无关
const int *p = nullptr; //p是个指向整型常量的指针
constexpr int *q = nullptr: //q是个指向整数的常量指针
处理类型
类型别名
typedef:将复杂的名称用其它简单明了的名称代替
typedef double wages; //wages是double的同义词
typedef wages base, *p; //base是double的同义词,p是double*的同义词
using(别名声明):也可以用来声明复杂类型
using SI = Sales_item; //SI是Sales_item的同义词
*大多数人往往错误地尝试把类型别名替换成原来的样子
typedef char* pstring;
const pstring cstr = 0; //cstr是个指向char的常量指针
const char* pstr = 0; //pstr是个指向常量char的指针
auto类型说明符
$不是所有时候都能准确的知道对象的对应的类型$
auto:根据变量的类型或者表达式所得的结果的类型来确定类型 -->对应的必须初始化
*auto 一般会忽略顶层const同时底层const会保留
const int ci = i = 0, &cr = ci;
auto b = ci; //b是一个整数(ci的顶层const特性被忽略掉了)
auto c = cr; //c是一个整数(cr是ci的别名,ci本身是一个顶层const)
auto d = &i; //d是一个整型指针(整数的地址就是指向整数的指针)
auto e = &ci; //e是一个指向整数常量的指针(对常量对象取地址是一种底层const)
decltype类型指示符
$代码的书写过程当中需要从表达式中判断出所需类型$
decltype():根据()内表达式输出的类型来决定变量类型
*decltype和引用-->对于decltype来说当括号里的类型是指针(解引用类型)或者内部再嵌一对 或多对括号(())时,返回的类型为引用,那么必须初始化以便绑定对象