指针:
因为指针的本身的值就是内存地址,它的占用字节数也就是该程序能够访问内存地址的空间大小,比如32位编译模式下,最大寻址为32位,2^32 B=4 GB,指针的值就是在 0x00000000 - 0xFFFFFFFF 范围内的值。因此指针本身占用的内存数和它指向的数据类型没有任何关系。
同理,64位编译模式下,理想的寻址位64位,也就是 2^64 B,这是个很大的值,而物理内存达不到这么大,CPU要实现64位的寻址能力只会增加系统复杂度和地址转换成本,因此Windows和Linux都做了限制,仅仅使用虚拟地址的48位,2^48 B=256TB。但是指针的占用内存字节数还是8 (只是Windows和Linux下,低48位有效而已)
bool | char | 指针 | short | int | long | longlong | float | double | |
32位 | 1 | 1 | 4 | 2 | 4 | 4 | 8 | 4 | 8 |
64位 | 1 | 1 | 8 | 2 | 4 | 4 | 8 | 4 | 8 |
指针数组 和数组指针:
数组指针: 指向数组的指针
指针数组: 数组元素全都是指针的数组
int arr[10];
&arr ; // 指向整个数组 步长为整个数组长度
&arr[0] ; // 数组首元素的地址
arr ; // 数组首元素的地址和&arr[0]一样
int* p1[10]; // 数组内包含10个int型指针 []优先级比*高 优先结合p1[10];
int(*p2)[10]; //指向10个int元素数组的指针
p2=&arr; //数组指针的初始化
(*p2)[2] // 使用数组指针
函数指针和指针函数:
指针函数:返回值为指针的函数
函数指针:指向函数的指针
int* test() { //返回值为int *的函数
}
int ADD(int a,int b){
return a + b;
}
int (*p3)(int , int ) = ADD; // 指向函数的指针
cout << (*p3)(2, 3);
cout << *p3(2, 3); // 两种调用方式结果是一样的
指针和引用的区别:
指针本身是一个对象,允许对指针赋值和拷贝,而且可以先后指向不同的对象。且无须在定义的时候初始化。
引用本身不是一个对象,而且必须在定义的时候初始化,相当于给引用的对象另起一个名字,并且从始至终,引用都和它的初始值对象一直绑定在一起。
const关键字:
const对象必须初始化。
默认状态下,const对象仅在文件内有效。如果在多个文件中想要用const,用extern声明。
const引用 :常量引用。引用的对象和自身都不可改变,而且不允许将引用的对象赋给非常量的引用。
const int a = 5; // 常量a
const int &a1=a; // 对常量的引用 对const的引用就是常量引用
int& a2 = a1; // 一个非常量引用 报错
int a = 5;
const int &a1=a;//可以 此时表示不可以用a1去修改a的值
a = 10;
cout << a1 << endl; //输出10
double dv = 3.23;
const int& a2 = dv;
dv = 4;
cout << a2 << endl; //此时输出3
// 编译器将上述代码改为如下形式:
const int temp=dv; //a2绑定了一个临时量 临时量是指编译器暂存表达式的求职结果临时创建的一个未命名对象
const int &a2=temp;
如果对象是一个const对象,那么用普通指针是无法指向该对象的,此时就要使用指向常量的指针。这里表示指针的指向可以改变,但是指针指向对象的值无法改变。
const int a = 5;
int* p = &a; // 错误 *p不可以指向const对象
const int* p1 = &a;
*p1 = 4; // 错误 无法改变值
const int* a; // 指向常量的指针 指针的指向可以改变 顶层const
int* const a; // 指针的值是一个常量 指针的指向不可以改变 底层const
//区别 底层const可以用于区分函数重载的形参 顶层const不可以