1.为什么传引用比传指针安全
由于不存在空引用,并且引用一旦初始化为指向一个对象,他就不能被改变为另一个对象。因此引用安全。
2.复杂指针
2.1一个有10个指针的数组,该指针是指向一个Int型的: int* a[10]
2.2一个指向有10个整形数数组的指针: int(*a)[10]
2.3一个指向函数的指针,该函数有一个整形参数并返回一个整形数: int(*a)(int)
2.4一个有10个指针的数组,该指针指向一个函数,该函数有一个整形参数并返回一个整形数:int (*a[10])(int)
2.5int (*(*func)[5])(int *p) : func被一个圆括号包含,左边有一个 * 号,所以func是一个指针。跳出括号,右边是一个[]运算符号,说明func是一个指向数组的指针。在往左看,左边有一个 * 号,说明这个数组的元素是指针;再跳出括号,右边又有一个括号,说明这个数组的元素是指向函数的指针。
总结,func是一个指向数组的指针,这个数组的元素是函数指针,这些指针指向具有Int * 类型的形参,返回值为Int型的函数
2.6int(*( * func)(int * p)[5] :func 是一个函数指针,这类函数具有int * 类型的形参,返回值是指向数组的指针,所指向的数组的元素是具有5个Int元素的数组
2.7总结:使用右左法则:首先从最里面的圆括号看起,然后往右看,在往左看。每当遇到圆括号,就应该掉转阅读方向。一旦解析圆括号里的所有东西,就跳出圆括号。
3.指针加减
对指针进行加1操作,得到的是下一个元素的地址,而不是原有地址直接加1。所以,一个类型为t的指针的移动,以sizeof(t)为移动单位。
int main()
{
int a[5]={1,2,3,4,5};
int *ptr=(int *)(&a+1);
printf("%d\n",*(a+1));
printf("%d\n",*(ptr-1));
}
- &a+1,即&a+sizeof(a),即&a+5*sizeof(int),即a[5]的地址,越界。
- 而 *(a+1)中,a与&a的地址是一样,但意思不一样。a是数组首地址,也就是a[0]的地址;&a是对象(数组)首地址。所以输出2。
- ptr指向a[5],ptr是int *类型,所以 * (ptr-1)指向a[4],输出5。
4.指针比较
int main()
{
char str1[]="abc";
char str2[]="abc";
const char str3[]="abc";
const char str4[]="abc";
const char* str5="abc";
const char* str6="abc";
char* str7="abc";
char* str8="abc";
cout <<(str1==str2)<<endl;
cout <<(str3==str4)<<endl;
cout <<(str5==str6)<<endl;
cout <<(str6==str7)<<endl;
cout <<(str7==str8)<<endl;
}
数组str1、str2、str3、str4都是在栈中分配的,内存中的内容相同,但是位置不同
指针str5、str6、str7、str8也是在栈中分配的,但是他们指向的“abc”存储在数据区。所以这四个指针指向同一块数据区的内存。
所以结果是
0
0
1
1
1
5、指针常量与常量指针
- 常量指针:是常量的指针。指向常量的指针。const int * p或者int const * p
- 指针常量:是指针的常量。是不可改变地址的指针。但是它所指向的内容可以修改。int * const p
- const int * const p :指针是常量,不可改变地址,所指向的内容也不可以修改。
6、this指针
- 类的非静态成员函数才有this指针
- 如果类的非静态成员函数里没有访问对象的任何数据成员,那么此时传进来的对象this 指针实际上是没有任何用处的。这样的函数与全局函数没有太大区别。