各类编程语言中的指针和引用

最近在用VC6作一个项目,有的弟兄反映不太理解指针和引用的区别。从目前现况来看,如今的开发人员用惯了Java,C#等语言,距离操做系统底层愈来愈远了,以致于大部分人对C/C++中的一些东西早已淡忘。
   说到指针,凡是学过c语言的人都不陌生,这是是c语言的精华所在。指针操做不只高效,并且很是接近系统底层,容易掌控。因此凡是使用c/c++编码的技术人员,我的建议是首先花精力把指针搞清楚。固然,事情老是具备两面性,有利必有弊,指针操做最为诟病的就是它的不安全性。除非你对它理解很透彻,不然不免会出现访问越界、内存泄露以及不可预知的结果。
   “引用”是C++中引入的概念,咱们常常会看到“引用”应用在函数调用过程当中。在C++语言中,调用一个函数时,参数传递能够采用3种方式:传值、传址和传引用。
好比下面一段VC代码:
  //主程序代码
  CString strUserId = "001";
  CString strUserName = "无名";
  BOOL bFind = FindUserName(strUserId, strUserName);
  if( bFind )
  {
     MessageBox("User Name:" + strUserName);
  }
  else
  {
     MessageBox("No found!");
  }
  //查找用户函数
  BOOL FindUserName(CString& strUserIdParam, CString& strUserNameParam)
  {
    if( strUserIdParam == "001" )
    {
      strUserNameParam = "王泽宾";
      return TRUE;
    }
    return FALSE;
  }
 
  FindUserName函数中使用了两个引用型参数。主程序代码最终的运行结果是:弹出一个对话框,内容是“User Name:王泽宾”。函数中的“CString &”,表示参数使用“传引用方式”。FindUserName中的strUserNameParam与主程序代码中的strUserName是同一个对象,因此修改他们中的任何一个,都会反映到另一个。strUserNameParam只不过是strUserName的别名而已,这很是相似于windows系统中文件的快捷方式,或者linux系统中文件的符号连接。
若是把查找用户函数修改成:
  //查找用户函数
  BOOL FindUserName(CString strUserIdParam, CString strUserNameParam)
  {
    if( strUserIdParam == "001" )
    {
      strUserNameParam = "王泽宾";
      return TRUE;
    }
    return FALSE;
  }
  FindUserName函数中使用了传值参数。主程序代码最终的运行结果是:弹出一个对话框,内容是“User Name:无名”。函数中的“CString”,表示参数使用“传值方式”。
   FindUserName中的strUserNameParam与主程序代码中的strUserName是彻底不一样的两个对象,因此修改他们中的任何一个,都不会反映到另一个上。strUserNameParam的内容复制了一份strUserName的内容,因此strUserNameParam又称为strUserName的副本,这个复制操做是在函数调用过程当中参数压栈时执行的。
若是把查找用户函数修改成:
  //查找用户函数
  BOOL FindUserName(CString *pstrUserIdParam, CString *pstrUserNameParam)
  {
    if( *pstrUserIdParam == "001" )
    {
      *pstrUserNameParam = "王泽宾";
      return TRUE;
    }
    return FALSE;
  }

  那么主程序代码中调用函数的地方须要略做修改:
  BOOL bFind = FindUserName(&strUserId, &strUserName);
  FindUserName函数中使用了传址参数。主程序代码最终的运行结果是:弹出一个对话框,内容是“User Name:王泽宾”。函数中的“CString *”,表示参数使用“传址方式”。FindUserName中的pstrUserNameParam与主程序代码中的pstrUserName是两个彻底没有关系的指针变量,只是这两个指针变量中存放的内容彻底相同,都是指向同一块内存空间的地址,因此修改他们中的任何一个指针变量所指向的内存空间,效果都是彻底同样的。pstrUserNameParam的内容复制了一份pstrUserName的内容,pstrUserNameParam是pstrUserName的副本,这个复制操做是在函数调用过程当中参数压栈时执行的。
   经过以上例子,咱们能够看到引用在做为函数参数传递时,具备指针的效果,可是却能够象传值的同样使用,方式比指针简单。看成为在参数时,经过指针和引用,均可以在函数体内操做直接改变他们所指向的地址空间里面存储的内容,无须编译器为他们建立一个临时变量复制并保存他们的值的一个副本。
   指针和引用在C/C++使用方法上,略有不一样:
  一、指针的值能够为 NULL ,而引用不能为 NULL,你若是VC中直接定义变量CString& strVar1;或者CString& strVar1 = NULL;这是行不通的,编译器没法经过语法扫描。编译器要求定义引用变量时,必须指定初值。
  二、一旦引用被初始化,就不能改变引用的关系(指针则能够随时改变所指的对象)。
如下示例程序中,k 被初始化为i 的引用。语句k = j 并不能将k 修改为为j 的引用,只是把k 的值改变成为6。因为k 是i 的引用,因此i 的值也变成了6。
int i = 5;
int j = 6;
int &k = i;
k = j; // k 和i 的值都变成了6;
  因此,咱们得出结论:引用实际上只是编程语言中语法层面的概念,经编译后实际执行的代码中与指针没有任何区别。引入这个概念后带来好处有两条:
一、代码简洁,使用方便。能够对比一下上面的例子。
二、部分消除指针使用的不安全。因为从语法层面就要求必须它初始化,因此不会出现空指针操做这样的危险状况。
   Java,C#语言的一个优势就是取消了指针的概念,从而从语法层面就消除了C/C++语言的不安全性,这对于构建健壮的大型应用很是有益。它们对于函数调用的参数传递采用两种方式:对于简单类型的参数实行传值方式,对于对象类型的参数实行传引用方式。
  以Java为例:
  class ObjUser{
    String strName = "init value";
    public String toString(){
        return strName;
    }
  }
public class Test{
    ObjUser User = new ObjUser();
    int Age = 60;
    public void changeObj(ObjUser user){
        user.strName = "changed value";
    }
    public void changeInt(int age){
        age = 80;
    }
    public static void main(String[] args)
    {
        Test objUser = new ObjUser();
        System.out.println("==================Print User=================");
        System.out.println("Before call changeObj() method: " + objUser.User);
        oRef.changeObj(objUser.User);
        System.out.println("After call changeObj() method: " + objUser.User);
        System.out.println("==================Print Age=================");
        System.out.println("Before call changeAge() method: " + Age);
        oRef.changePri(objUser.Age);
        System.out.println("After call changeAge() method: " + Age);
    }
}
运行结果:
==================Print User=================
Before call changeObj() method: init value
After call changeObj() method: changed value
==================Print Age=================
Before call changeAge() method: 60
After call changeAge() method: 60
  在Java中若是要实现对象传值方式,能够先借助于clone()方法先来复制对象,而后再调用函数。
 C#的情形基本相似,php中也保留了传值和传引用两种方式,跟C++的语法相似。

本文来自CSDN博客,转载请标明出处: http://blog.csdn.net/wanghao72214/archive/2009/07/24/4376158.aspx
相关文章
相关标签/搜索