token法: 指针名本身有地址(有地址的数据也能说成对象),指针名保存的是别人的地址(称别人的地址为该指针名所含有的值)
引用名本身没有地址(不是对象,不能被指向和对引用名在进行引用),定义引用名时必须初始它的值
int a = 1; // a 是一个变量名,变量名的值为1,同时a是一个对象(因为a本身是有地址的)
int *p_a = &a; // 取a的地址,对a指向,指针的设计是利用内存,指针的大小是固定的,但是自定义类的大小未定,使用指针比使用自定类型本身更高效
int &ref_a = a;//对a起别名
int const &const_ref_a = a; // 如果你不想这个引用破坏a本身的值,你因该使用const,此时的const与写在int前是等价的
对常量引用就应该使用常引用
const float PI = 3.14;
const float &ref_pi = PI;
对指针说法:顶层const和底层const
const int a_value = 1;
const int *const p_a_value = &a_value; // 靠最近p_a_value指针的称为顶层指针,表示这个指针名不能再指向其他值,底层指针表明p_a_value指向的值本身也就是一个const
数组叫做派生类型,数组名本身也就算一个地址,函数名也同理,但是对于重载,我建议少用函数重载或者不用是最好的
// 对一维数组,多维有点复杂,函数也很复杂
int array[3] = {1,2,3};
int *p_array = array; // 此时你应该把p_array完全等价于array的使用方法
p_array[1] = 10;
cout << p_array[1] << endl;
// 如果你不想修改array,你应该使用const
const int *const_p_array = array;
// 现在你不能这样做 const_p_array[1] = 20;
token是这样的,他告诉我有var_name,有var_value,有keyword,我们要做的就是分析上面三种东西
指针在数组和函数上的4个用法
// 对于指针数组,数组指针,函数的指针式用法
#include <iostream>
using namespace std;
int main(){
// 原生数组
int arr[10]{1,2,3};
for(auto &x: arr){
cout << x << " ";
}
cout << endl;
// 数组指针
auto parry = arr;// parry: int* ,然而不建议`自己指明指向数组的指针parry的类型`,因为我提前就知道arr的大小了,我只是再用parry去别名arr
parry[4] = 199;
parry[5] = 200;
cout << *(parry+5) << endl;// 200
cout << *(arr+5) << endl;// 200 所以arr和parry其实理解为一个东西
cout << &arr << " " << &parry << endl;// 只有arr和parry的地址是有差异的
for(auto &x:arr){
cout << x << " ";
}
cout << endl;
// 指针数组
int *(ptr_array)[10] { nullptr};
ptr_array[0] = &arr[0];
ptr_array[1] = &arr[4];// arr[4] = 199
cout <<"指针数组: " << *ptr_array[0] << endl;//解饮用,否则ptr_array[0]输出一个地址,0x开头
cout <<"指针数组: " << *ptr_array[1] << endl;//解饮用,否则ptr_array[0]输出一个地址,0x开头
cout << "如果指针数组取一个值是nullptr再解饮用,它是不输出到终端的: " << *ptr_array[9] << endl;//因为nullptr不引用任何值和对象
// 函数部分
auto p = [](int){
int a = 10;
int *pa = &a;
return pa;};
auto q = [](int){
return 1;
};
auto pvalue = p(10);
cout << *pvalue << endl;
auto value = q(10);
cout << value << endl;
return 0;
}