zoukankan      html  css  js  c++  java
  • [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);  

    总之指针还得多使用,能用熟最好,不然最好不用,用引用去代替它,

    如果到什么开发什么程序的时候,程序崩溃了,都不知道为什么,那

    可就糟了

  • 相关阅读:
    mysql主从与mycat与MHA
    mycat+mysql集群:实现读写分离,分库分表
    centos7下扩展根分区(图文详解)
    MySQL高可用之MHA的搭建
    zabbix_agentd客户端安装与配置(windows操作系统)
    centos7手把手教你搭建zabbix监控
    有关添加System.Web的问题
    锚标签<a>
    MVC3出现“提供程序未返回 ProviderManifestToken 字符串”的解决办法
    解决.net后台调用js弹窗后,前台界面样式乱掉问题
  • 原文地址:https://www.cnblogs.com/yyf0309/p/5677306.html
Copyright © 2011-2022 走看看