首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

《小弟我的第一本C++书》节选:7.1.4 指针在函数中的应用

2014-01-05 
《我的第一本C++书》节选:7.1.4 指针在函数中的应用http://www.chenlq.net/指针因其在访问内存上的灵活性而

《我的第一本C++书》节选:7.1.4 指针在函数中的应用
http://www.chenlq.net/


指针因其在访问内存上的灵活性而出名,当它跟函数搭配使用的时候,可以大大提高函数的灵活性,增加函数的威力。指针在函数中的应用主要包括两个方面:指针作为函数参数和指针作为函数的返回值。

    指针作为函数参数 在大多数情况下,函数之间参数的传递,都是通过传值来完成的。参数的传值传递要对数据进行拷贝,如果要传递的数据比较大,比如要向函数传递一个数组,则会增加函数调用的开销。这时,可以利用指针作为函数参数。在函数内部,利用指针能够灵活访问内存的特性,可以通过指针来访问需要传递进函数的数据,以此来完成大量数据的传递,减少函数调用的开销。使用指针作为函数参数,不仅可以向函数传入数据,还可以向函数的调用者传出数据。因为函数的调用者和函数都可以使用指向同一内存地址的指针,也就是使用同一块内存,所以使用指针作为函数参数时,就是对同一数据进行读/写操作,这样不仅可以传入数据,还可以通过在函数内部修改这些数据,把函数的结果传出给调用者。下面来看一个使用指针作为函数参数的实际例子:

     
    
    
    // 计算数组中所有数据之和的函数
    // 其中,参数pArray 和nArrayCount分别
    // 表示数组的首地址和数组元素的个数,
    // 用于向函数传入一个数组,
    // nSum表示最后求得的数组所有数据之和,用于从函数中传出计算结果
    void SumArray(int* pArray, int nArrayCount, int* nSum )
    {
        *nSum = 0;
     
        // 循环遍历整个数组
        for( int i = 0; i < nArrayCount; ++i )
        {         
            // 通过指针访问数组元素,
            // 同时通过指针访问保存结果的变量,
            // 实际上也就是对主函数中nArraySum变量的访问
            // 将结果保存到nArraySum中,传出结果
            *nSum += *pArray;
            pArray++;   // 指针加运算,访问数组中的下一个元素
        }
    }
     
    int _tmain(int argc, _TCHAR* argv[])
    {
        // 定义保存结果的变量和数组
        int nArraySum;
        int nArray[5] = { 1, 2, 3, 4, 5 };
     
        // 使用数组的地址nArray传入数组,
        // 使用指向变量nArraySum的指针来接收计算结果
        SumArray(nArray, 5, &nArraySum); 
               
        // 运算结果已经保存在nArraySum中,输出运算结果
        cout<<"数组中所有数据之和是 :"<<nArraySum<<endl;
     
        return 0;
    }

    在主函数中,调用了数组求和函数SumArray(),并将数组的起始地址nArray和保存结果的整型变量的地址&nArraySum传递给了求和函数。在求和函数SumArray()中,通过传入的数组地址访问整个数组,完成传入数据的功能。同时,利用指向保存结果变量的指针,将结果直接保存到变量nArraySum中,完成传出数据的功能。利用指针作为函数参数传递数据的本质,就是在主调函数和被调函数中,通过指向同一内存地址的不同指针访问相同的内存区域,从而实现数据的传递和交换。图7-3展示了指针作为函数参数访问相同内存的结果。

    clip_image002

    图7-3  指针作为函数参数访问相同内存
    指针作为函数返回值 指针作为一种基本数据类型,同样可以作为函数的返回值。当函数的返回值是指针时,这个函数就是指针型函数。指针型函数通常用来获取一些指针变量的值,例如,在开发实践中经常使用的用于获得主窗口指针的函数GetMainWnd()就是一个指针型函数:

     
    1
    
    CWnd* GetMainWnd();

    另外,使用指针作为函数返回值,还可以将大量的结果数据以指针的形式从被调函数返回到主调函数中,起到传出结果数据的作用。这点跟使用指针作为函数传出参数相似。 这里需要特别注意的是,不能把一个指向局部变量的指针作为返回值。这是因为函数内部声明的局部变量在函数结束后,其生命周期已经结束,内存会被自动释放,这时它的内存地址是无意义的。如果将其作为函数返回值返回给主调函数,并在主调函数中访问这个指针所指向的数据,将产生不可预料的结果。例如下面的例子:
    
    
    // 从函数中返回一个局部变量的指针
    int* GetLocalVal()
    {
        // 声明一个局部变量
        int nLocalVal = 1;
        // 返回局部变量的指针
        return &nLocalVal;
    }
     
    int _tmain(int argc, _TCHAR* argv[])
    {
        // 获取从函数中返回的局部变量指针
        int* pLocalVal = GetLocalVal();
        // 输出当前局部变量的值
        cout<<"当前局部变量的值是:"<<*pLocalVal<<endl;
     
        // 改变内存内容
        int a;
         
        // 再次输出局部变量的值
        cout<<"改变内存后,当前局部变量的值是:"<<*pLocalVal<<endl;
        return 0;
    }

    执行程序后,可以得到这样的输出结果:当前局部变量的值为1。 改变内存后,当前局部变量的值是:1580854592。 从输出结果中可以清楚地看到,第一次输出时得到的是正确的结果。当声明一个新的整型变量、改变内存的内容再次输出时,得到的就是一个不确定的数值。这是为什么呢?因为调用的GetLocalVal()函数返回后,虽然局部变量nLocalVal已经不存在,但是存放它的内存中的值并没有改变,这时输出得到的还是它原来的值。但是当声明一个新的变量、改变这部分内存中的值时,则第二次输出的是一个不确定的值。因为在内存未改变时,通过指向函数局部变量指针得到的正确的值,往往使这种错误具有很大的隐藏性,这点尤其需要我们高度警惕,防止从函数中返回一个指向局部变量的指针。牢记下面的规则:指针函数可以返回全新申请的内存地址;可以返回全局变量的地址;可以返回静态变量的地址,但就是不可以返回局部变量的地址。



热点排行