`
huanggaole
  • 浏览: 10064 次
  • 性别: Icon_minigender_1
最近访客 更多访客>>
社区版块
存档分类
最新评论

JAVA转型C++(二):引用与指针

 
阅读更多
引用与指针
一、引用
    引用为变量提供了一个别名,对引用所作的任何操作都作用于它所指向的对象。声明方式:
int& score = myScore;

    注意:1.引用必须在声明的时候指向另一个值,如果不对其进行初始化会导致编译错误。
          2.关于引用运算符&的位置,可以是"int& score"或"int & score"或"int &score"都可以,但是它只能修饰离它最近的变量名。例如:"int& score = myScore,age = myAge;"中,只有前者的score引用了myScore,后者的age是普通的数值赋值。
          3.引用的关联只在声明时创建,之后对引用变量的赋值都是对与之关联的变量进行操作。例如:"int& score = myScore;score = hisScore;score = 100;"的作用是声明了一个与myScore关联的引用,然后将hisScore赋值给myScore,然后将100赋值给myScore,至始至终hisScore的数值没有发生改变。

    C语言中也有按值传递与引用传递,在JAVA中,函数间进行传参时,基本数据类型是值传递,对象类型是引用传递。而在C++中,则根据声明的参数来确定是值传递还是引用传递。例如:
void swap1(int a,int b);  //值传递,函数中的参数a,b不会对传入的实参产生影响
void swap2(int& a,int& b);//引用传递,函数中的参数a,b就是传入参数的别名。


    值传递是将实参进行一次拷贝生成了形参,形参具有独立的内存空间且其改变不会影响到实参。但是这种传递是要进行复制的,当传入的是结构体、对象或大数组时,值传递十分低效。因此当函数中的形参值不需要改变,只是用来读操作的话,可以用常量引用声明参数:
void display(const vector<string>& vec);//引用传递向量,不允许函数对其修改


    同理,在返回一个数据并赋值时,同样要进行拷贝操作。如果返回的类型过大,我们也可以考虑返回一个引用:
string& refToMain(vector<string>& inventory, int i)
{
    return inventory[i];
}

    以上函数返回的是向量inventory中第i个元素的值。主函数中可以声明一个引用来接收该函数的返回值:
string& rStr = refToMain(inventory,1)

    由于是引用返回,因此不需要进行拷贝操作。但是要注意的是,必须保证函数结束后,返回的引用还在。例如下面的函数是不可取的,因为它返回的引用在函数结束后将不复存在:
string& refToMain()
{
    string s = "stringwilldestroy";
    return s;
}


二、指针
    指针的本质是一个包含内存地址的变量。指针的声明方式如下:
int* pAPointer = 0;

    注意:1.与引用运算符&类似,星号的位置也有三种情况,都可以。而且也只能修饰最近的那个变量。
          2.以上将0赋给指针有特殊的含义,即该指针不指向任何内存。或在定义时指向NULL(iostream中的常量)。
   
    因为指针存储对象的地址,所以需要有为指针赋予地址的方法。一种方法是获取已有变量的内存地址,并将其赋值给指针。如下面代码所示:
int* pScore;
int score;
pScore = &score;

    这里的“&”是放在变量前的,它的作用是取地址,因此在这里它叫取址运算符。
    而要用pScore来访问score则需要用到解引用。前面的迭代器已经提到过,解引用运算符“*”。以下代码是用来访问score中的值:
*pScore = 100;//这一句与score = 100;是同一个效果 

    注意:1.不要对空指针做解引用操作。
          2.修改指针指向的对象的值时不要修改指针的值。例如pScore + 500并不是对score增加500,而是将存储在pScore中的地址增加500指向了另一块内存空间。
    另外特别注意以下的写法,这是用来获取score的地址:
cout << pScore;//这一句与cout << &score;是同一个效果,输出的是score这个变量的内存地址。 

    与引用不同,指针可以在程序运行期间的不同时刻指向不同的对象。对指针重新赋值与变量的重新赋值一样。下面一行代码对pScore进行了重新赋值。
pScore = &newScore;//注意*pScore = newScore;则是将newScore的值赋给score

    指针可以使用“->”运算符以一种更具有可读性的方式来访问对象成员。例如:
cout << pStr->size();
cout << (*pStr).size();

    这两条语句是等价的。但是上面一条更具有可读性。
   
    引用中常量引用。同样的,指针中也有常量指针。通过在声明和初始化指针时使用const来限制指针的行为。这些限制如同保护措施,可以让程序的意图更加明确。例如以下语句:
int score = 100;
int * const pScore = &score;

    上面的代码创建了一个指向score的常量指针pScore。创建的方法是在声明时将const置于指针名称之前。第一次声明常量指针时必须对其进行初始化。实际上常量指针与引用是可以相互转化的。
    pScore是常量指针,因此它永远不能指向其他任何内存地址,但是可以用它来改变其指向的值。这一点跟引用是很类似的。
   
    除了常量指针外,还有一种用const来修饰的指针,可以实现无法用该指针来修改其指向的值。这种指针叫做指向常量指针。声明的方式是将const关键字置于指针所指向值的类型之前。例如以下语句:
const int* pNumber;

    这种声明方式可以不给指针赋初值,而且在编程中可以改变指针的指向,但是不能修改这个指针所指向的变量的值。例如下面的代码是非法的:
*pNumber = 1;


    如果希望指针所指的变量不能改变,指向变量的值也不能修改,那么只需要结合常量指针与指向常量指针就能定义指向常量的常量指针。例如以下语句:
const int* const pBONUS = &BONUS;

    顾名思义,指向常量的常量指针是限制条件最多的一条指针,它既不能改变指向,也不能修改指向的变量,而且定义时必须赋初值。

    对于C++,在函数传递中,除了值传递和引用传递,还有第三种传递,就是指针传递。其实原理跟引用传递差不多,而指针与引用本身就是一种原理。所以在此不再赘述。

    还要注意一点,那就是指针与数组有着密切的联系。实际上,数组名是指向数组第一个元素的常量指针。因为数组元素存储在连续的内存块中,所以可以把数组名当做指针使用来实现数组元素的随机访问。
   
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics