指针难点:(这东西都快忘了,还好学的时候总结过,不用重新整理)
二维数组中a+i, &a[i], a[i], *(a+i)的值相同,含义不同。
a+i与&a[i]表示第i行的首地址,指向行,a[i], *(a+i), &a[i][0]表示第i行第0列元素的地址,指向列。
&a[i]是列指针a[i]加取地址符号后得到的行指针
*(a+i)是有行指针a+i加上*变成的列指针。
在行指针前面加上*就变成了列指针,在列指针前面加上&就变成了行指针
地址间课以进行运算,可以求差值,也可以进行比较
/*地址间进行运算的时候,比如cha = p1 - p2; 那么cha记录的是他们相差的字节数,记住运算结果是字节数哦*/ //地址可以求差,也可以进行比较 #include <iostream> using namespace std; int main() { int *p = new int; cout << "p: " << p << endl; int *p1 = new int ; cout << "p1: " << p1 << endl; *p = p - p1; cout << "两块地内存的地址差" << *p << endl; if(p > p1) cout << "p大于p1的内存地址" << endl; else cout << "p小于p1的内存地址" << endl; return 0; }
this指针:代码如下
/*this指针保存了对象的地址,因此你可以通过该指针直接读取某个对象的数据 this指针可以省略不写,编译器会自动在成员变量前面加上this指针,用来表示这个i成员是属于某个对象的 this指针的创建与删除由编译器来完成*/ #include <iostream> using namespace std; class A { public: int get() const{return i;} void set(int x){this->i = x; cout << "this变量保存的内存: " << this << endl; } private: int i; }; int main() { A a; a.set(9); cout << "对象a的内存地址: " << &a << endl; cout << a.get() << endl; A b; b.set(999); cout << "对象b的内存地址: " << &b << endl; cout << b.get() << endl; return 0; }
根据上面代码我们可以发现,不同对象的this指针是不一样的,我们要知道this指针保存的是对象的地址,他用来表示某个成员变量所属的对象
指针不用的时候不清零容易引发的危险错误的演示代码
/*如果指向堆的指针不用的时候没有被清零,它将会导致这个指针会随意修改这个内存空间的数据, 如果这个内存空间被程序中的其他变量使用,这个指针就有可能修改使用这个空间的这个变量的数值, 这样引发的错误是非常难调试的 清零之后如果直接引用这个指针里面保存的数据会引发程序崩溃,因为空指针不能被引用,但是这样的错误比较容易发现, 因此,我们宁愿程序崩溃,也不愿出现因为指针不用时候没有清零而引发的那些比较难发现的错误*/ #include <iostream> using namespace std; int main() { int *p = new int; *p = 3; cout << "创建新空间前,指针p保存的地址为: " << p << endl; cout << "将3赋给p的地址后,指针p所读取的值 " << *p << endl; delete p; cout << "创建新空间后,指针p保存的地址为: " << p << endl; cout << "删除空间后指针p读取的值: " << *p << endl; long *p1 = new long; cout << "创建新空间后,指针p保存的地址为: " << p << endl; cout << "创建新空间后,指针p1保存的地址: " << p1 << endl; *p1 = 999999; cout << "将999999赋给p1的地址后,指针p读取的值: " << *p << endl; cout << "将999999赋给p1的地址后,指针p1读取的值: " << *p1 << endl; *p = 23; cout << "将23赋给p的地址后,指针p读取的值: " << *p << endl; cout << "将23赋给p的地址后,指针p1读取的值: " << *p1 << endl; delete p1; return 0; }
我们定义一个指针就一定要用他保存一个内存地址,加入我们不这样做,
那么该指针就是一个失控指针他可以指向任何地址,并且对该地址的数值进行修改或删除,后果是非常可怕的
解决办法是将该指针初始化为0,即p = 0;该语句是将p所保存的地址清零,
(即让p指向00000000这个地址,这个地址是不会存放任何数据的,因此我们对它进行的任意操作都不会产生严重后果)
这样p就不会因为我们的疏忽而修改它指向的地址(随机)的值
由于指针类型不同决定了指针的运算方式不同,所以我们不能将一种类型的指针赋给另一种类型的指针
可以用如下代码验证,计算地址变化前后的差值就会发现,不同类型的指针数据,自加之后的值和原来的值得差是不一样的
因此我们也不能将一种类型的指针的值赋给另一种类型的指针,否则会报错
#include <iostream> using namespace std; int main() { double a = 3.14; int b = 6; double *p = &a; int *q = &b; cout << "p:" << p << endl; cout << "q:" << q << endl; p++; q++; cout << "p:" << p << endl; cout << "q:" << q << endl; return 0; }
下面程序演示指针使用之前一定要初始化,区分指针地址,指针保存的地址和该地址的值
#include <iostream> using namespace std; int main() { int i; int *p = 0; //指针使用之前一定要初始化,如果没有要让它指向的地址,就把它初始化为0,否则很危险!!!!! cout << "i的地址为:" << &i << endl; cout << "p的值为:" << p << endl; cout << "p的内存地址为:" << &p << endl; i = 3; p = &i; cout << "i的地址为:" << &i << endl; cout << "p的值为:" << p << endl; cout << "p的内存地址为:" << &p << endl; return 0; }