[c/c++]指针(4)
现在讲一下指针的主要用途和常见错误。
[用途]
1.用作形参
首先,常见新手写交换函数:
1 void swap(int a,int b){ 2 int t = a; 3 a = b; 4 b = t; 5 }
主函数里调用一下试试,看看a,b的值有没有改变?
1 #include<iostream> 2 #include<stdlib.h> 3 using namespace std; 4 void swap(int,int); 5 int main(){ 6 int a = 2; 7 int b = 1; 8 swap(a,b); 9 cout<<a<<" "<<b; 10 return 0; 11 } 12 void swap(int a,int b){ 13 int t = a; 14 a = b; 15 b = t; 16 }
运行结果就不公布了,对于新手,有木有发现什么不对的地方?
是什么原因造成这个结果的呢?应该是内存地址吧,要同一内存地址修改其中一个的值
才会改变另一个的值,那来验证一下:
#include<iostream> #include<stdlib.h> using namespace std; void swap(int,int); int main(){ int a = 2; int b = 1; cout<<"address in main: &a = "<<&a<<" &b = "<<&b<<endl; swap(a,b); cout<<a<<" "<<b; return 0; } void swap(int a,int b){ int t = a; a = b; b = t; cout<<"address in swap: &a = "<<&a<<" &b = "<<&b<<endl; }
运行结果
address in main: &a = 0x22fedc &b = 0x22fed8 address in swap: &a = 0x22fec0 &b = 0x22fec4 2 1
看来确实是这样的。。。
那么要是swap和main函数中a,b两变量的内存地址相等,可以用指针来完成
1 #include<iostream> 2 #include<stdlib.h> 3 using namespace std; 4 void swap(int*,int*); 5 int main(){ 6 int a = 2; 7 int b = 1; 8 cout<<"address in main: &a = "<<&a<<" &b = "<<&b<<endl; 9 swap(&a,&b); 10 cout<<a<<" "<<b; 11 return 0; 12 } 13 void swap(int* a,int* b){ 14 int t = *a; 15 *a = *b; 16 *b = t; 17 cout<<"address in swap: &a = "<<a<<" &b = "<<b<<endl; 18 }
运行结果
address in main: &a = 0x22fedc &b = 0x22fed8 address in swap: &a = 0x22fedc &b = 0x22fed8 1 2
(注:如果读者知道,其实还有一种代码写起来可读性比指针高,错误率比指针低的方式,就是用引用&)
2.提高运行速度
随便打了篇代码来做实验,第一个seta函数是不用指针给结构体中的数据赋值,第二个setb函数时用指针给
结构体中的数据赋值
1 #include<iostream> 2 #include<ctime> 3 using namespace std; 4 struct a{ 5 int a[100000]; 6 int len; 7 }c; 8 a seta(a b,int index,int val){ 9 b.a[index] = val; 10 return b; 11 } 12 a setb(a *b,int index, int val){ 13 b->a[index] = val; 14 return *b; 15 } 16 int main(){ 17 clock_t begin = clock(); 18 for(int i = 0;i < 1000;i++) 19 c = seta(c, i, i); 20 clock_t end = clock(); 21 22 clock_t begin1 = clock(); 23 for(int i = 0;i < 1000;i++) 24 c = setb(&c, i, i); 25 clock_t end1 = clock(); 26 27 cout<<"非指针:"<<(end - begin)<<"ms"<<endl; 28 cout<<"指针 :"<<(end1 - begin1)<<"ms"<<endl; 29 return 0; 30 }
运行结果(鉴于我家渣机外加开了很多程序所以运行地很慢):
非指针:1781ms
指针 :672ms
有木有发现什么明显的差距,稍微微调一下,把setb函数改成:
void setb(a *b,int index, int val){ b->a[index] = val; }
然后编译运行,神奇的事发生了:
非指针:1078ms
指针 :0ms
是不是很神奇?
想知道这是为什么吗?
因为在结构体传递的时候是值传递,又因为数组很大,所以要拷贝过来,赋值的
时候也是需要拷贝,所以非常消耗时间,而指针是地址传递,相当于是一个要复制
一个数组,而另一个却只用复制4字节的数据就完成了一样的事
其实还可以比较一下,指针和引用的时间消耗:
1 #include<iostream> 2 #include<ctime> 3 using namespace std; 4 struct a{ 5 int a[1000000]; 6 int len; 7 }c; 8 void seta(a& b,int index,int val){ 9 b.a[index] = val; 10 } 11 void setb(a *b,int index, int val){ 12 b->a[index] = val; 13 } 14 int main(){ 15 clock_t begin = clock(); 16 for(int i = 0;i < 1000000;i++) 17 seta(c, i, i); 18 clock_t end = clock(); 19 20 clock_t begin1 = clock(); 21 for(int i = 0;i < 1000000;i++) 22 setb(&c, i, i); 23 clock_t end1 = clock(); 24 25 cout<<"引用:"<<(end - begin)<<"ms"<<endl; 26 cout<<"指针:"<<(end1 - begin1)<<"ms"<<endl; 27 return 0; 28 }
结果可以多运行几次,不行可以加大数据,指针和引用貌似时间消耗差不多,不过引用写起来是要
比指针简单一些,像这样也就最多有10ms
3.用于各种数据结构
例如各种树结构,链表等
4.给指定内存存储的数据赋值(在开发操作系统时,这貌似是允许的)
5.通过new、malloc等来省内存
[常见错误]
1.空内存地址
当一个指针的值等于 0x00(NULL,windef.h下定义)时,这必定是一个空内存,如果用到了访问*,程序直接崩溃,访问无效内存
还有就是与其它程序或者系统的专用内存段等冲突,也会导致程序崩溃,这就是因为即使有时候数组下标超了一点点时也可能不会崩溃
的原因
2.访问用过delete或free()后的指针
3.滥用指针,导致浪费内存
另外指针经常也很难看懂,比如,你能一样告诉我这是什么类型的指针吗?(下)
typedef char*const(*p)(long long);
总之指针还得多使用,能用熟最好,不然最好不用,用引用去代替它,
如果到什么开发什么程序的时候,程序崩溃了,都不知道为什么,那
可就糟了