c/c++面试23-29
23 一般引用的用法
(1)代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <string> 3 using namespace std; 4 int main(int argc, char* argv[]) 5 { 6 int a = 10; 7 int b = 20; 8 int &rn = a;//声明rn为变量a的引用 9 int equal; 10 11 rn = b;//rn是a的别名 也就是b赋值给rn实际上就是修改了a的值 引用不用开辟内存单元 12 cout << "a=" << a << endl;//10 13 cout << "b=" << b << endl;//20 14 15 rn = 100; 16 cout << "a=" << a << endl;//100 17 cout << "b=" << b<< endl;//20 18 19 equal = (&a == &rn) ? 1 : 0; 20 cout << "equal=" << equal << endl;//1 21 22 getchar(); 23 24 return 0; 25 26 }
(2)分析
a:rn其实是a的一个别名,对rn的赋值实际上就是对a的赋值,因此执行完赋值以后,a的值就是b的值
b:rn声明为a的引用,不需要为rn另外开辟内存单元,它们占用的是同一个存储单元
24 指针变量的引用
(1)代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <stdio.h> 2 #include <iostream> 3 4 using namespace std; 5 6 int main() 7 { 8 int a = 1; 9 int b = 10; 10 int *p = &a;//指向整形变量aa的p 11 int* &pa = p;//p的指针引用pa 12 13 (*pa)++;//pa+1实际上就是对p指向的内容加1 也就是a+1 所以a=2 14 cout << "a=" << a << endl;//2 15 cout << "b=" << b<< endl;//10 16 cout << "*p=" << *p << endl;//2 17 18 pa = &b;//pa是p的引用 所以p也指向了b的地址 19 (*pa)++;//实际上就是对p指向的内容加上1 20 cout << "a=" << a << endl;//2 21 cout << "b=" << b << endl;//11 22 cout << "*p=" << *p<< endl;//11 23 getchar(); 24 return 1; 25 26 27 }
(2)分析
a:声明p的一个指针引用pa,pa指向的内容+1,因为pa是p的引用,所以实际上是对p指向的内容加1也就是a+1结果为2
b:pa指向变量b的地址,因为pa是p的引用,所以此时p也指向b的地址
25 看代码找错误
(1)代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <stdio.h> 2 #include <iostream> 3 4 using namespace std; 5 int main(int argc, char** argv) 6 { 7 8 int a = 1; 9 int b = 2; 10 //int &c;引用声明必须初始化 11 //int &d = a; 12 //&d = b;引用只能在声明的时候赋值 13 //int *p; 14 //*p = 5;因为p没有初始化 野指针 15 16 getchar(); 17 return 1; 18 19 }
(2)分析
a;引用类型的变量声明的同时必须初始化
b:引用只能在声明的时候被赋值,以后不能用该引用名作为其他变量的别名
26 如何交换两个字符串
(1)代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <stdio.h> 2 #include <iostream> 3 4 using namespace std; 5 //传递引用实现交换 6 void swap(char *&x, char *&y) 7 { 8 char *temp; 9 temp = x; 10 x = y; 11 y = temp; 12 } 13 14 //使用二级指针处理方案 15 void swap1(char **x, char**y) 16 { 17 char *temp; 18 temp = *x; 19 *x = *y; 20 *y = temp; 21 } 22 int main(int argc, char**argv) 23 { 24 char *ap = "hello"; 25 char *bp = "how are you"; 26 cout << "ap:" << ap << endl; 27 cout << "bp:" << bp << endl; 28 29 swap(ap, bp); 30 31 cout << "swap ap bp" << endl; 32 cout << "ap:" << ap << endl; 33 cout << "bp:" << bp << endl; 34 swap1(&ap, &bp); 35 cout << "swap1 ap bp" << endl; 36 cout << "ap" << ap << endl; 37 cout << "bp" << bp << endl; 38 getchar(); 39 return 0; 40 }
(2)分析
a:这是利用指针引用实现字符串的交换,也可以通过二维指针达到同样的目的
27 指针和引用有什么区别
a:初始化不同,引用在创建的同时必须初始化,也就是引用的一个有效的对象那里
b:可修改行不同,引用一旦被初始化指向一个对象,它就不能改变另一个对象的引用,也就是不要脚踏两只船。
c:不存在NULL的引用,引用不能指向空值的引用
d:测试需要的区别。引用不会指向空值,也就是不用测试他的有效性
28 为什么传引用比传指针更加的安全
a:由于不存在空引用,并且引用一旦初始化为指向的一个对象后不能被改变为另一个对象的引用
29 复杂指针的声明
(1)
a;int **a;//指向一个存储为指针的指针变量
b:int *a[10];//一个有10个指向整型的指针的数组
c:int (*a)[10];//一个指向有10个元素的整形数组的指针
d:int (*a)(int);//一个指向函数的指针,这个函数有一个整型参数并返回一个整形数
e:int (*a[10])(int);//一个有10个指针的数组,该指针指向一个函数,这个函数有一个整形参数并返回i一个整形数
(2)复杂情况的解析
a:法则
右左法则,首先从未定义的标识符开始看,然后看最里面的圆括号,然后看右边再看左边,遇到圆括号再掉转方向,解析完一个括号再跳出圆括号,重复过程
b:eg1
int (*func)(int *p)
首先找到那个未定义的标识符,func,外面一层符号,而且左边是一个指针,所以func是一个指针;然后跳出圆括号发现右边是一个括号,说明(*func)是一个函数,而func是一个指向这类函数的指针,也就是函数指针,int*为形参
c eg2
int (*func)(int *p,int (*f)(int*))
func被一个括号包含而且左边是一个*号,说明func是一个指针,跳出括号,右边又是一个括号,说明是一个指向函数的指针,这个函数形参一个是int*,一个是int (*)(int*),返回值是int *.类似的,f也是一个函数指针,指向函数具有int*类型的形参,返回值为int
d:int (*func[5])(int *p)
func右边是一个[]运算符,说明func是具有5个元素的数组.func左边有一个*,说明func是一个指针,因为[]运算符优先级比*高,所以func先和[]结合,因此*是修饰func[5]。跳出括号再看右边,也是圆括号,那么说明func数组元素是函数类型的指针,它指向的函数是int*类型的形参。
e:int (*(*func)[5])(int *p)
func是一个圆括号,左边有一个*,func是一个指针。跳出括号,右边是一个[]运算符,说明func是一个指向数组的指针。看左边,左边有一个*,说明这个数组元素是指针;再跳出括号,右边还是一个括号,说明这个数组的元素是指向函数的指针。总之,func是一个指向数组的指针,这个数组的元素是函数指针,这个指针指向具有int*类型的形参,返回值为int类型的函数
f:int (*(*func)(int *p))[5]
func是一个函数指针,这类函数具有int*类型的形参,返回值是指向数组的指针,所指向的数组元素是具有5个int元素的数组
好了,加油!!