熟悉C/C++编程语言的朋友都知道,在C/C++中对于有些运算符和关键字在不同场合会有不同的语义,有时甚至是截然不同。比如,在作为双目运算符时,*表示乘法运算;&表示按位相与运算。而作为单目运算符时,*表示取指针所指地址的内容;&表示取变量地址或脱去解引用(参考http://blog.youkuaiyun.com/zenny_chen/archive/2008/06/04/2512056.aspx)。然而,对于一种变量在不同场合下会有不同的效果,这个可能在其它编程语言中也不多见吧?在C语言中似乎没有,但是在C++中却有。
由于C++有操作符重载以及对象类型转换,使得C++对象作为左值和右值可以有截然不同的行为,参照以下代码:
- #include <iostream>
- using namespace std;
- class Test
- {
- private:
- const char* name;
- int* pValue;
- public:
- Test(const char* n) : name(n)
- {
- }
- const int& operator = (int& i)
- {
- pValue = &i;
- return *pValue;
- }
- operator const char* (void)
- {
- return name;
- }
- void Output(void)
- {
- cout << "The name is: " << name << endl;
- if(pValue == NULL)
- cout << "The value is null!" << endl;
- else
- cout << "The value is: " << *pValue << endl;
- }
- };
- int main(void)
- {
- int a;
- Test t("Hello");
- t = a = 10;
- const char *p = t;
- cout << "p is: " << p << endl;
- t.Output();
- return 0;
- }
下面我们将介绍C++特有的一种内在语法——引用。
对C++比较熟悉的朋友应该知道,当一个引用指向一个变量时,如果变量引用被赋予另一个值,那么被引用的变量的值也会被相应改变。如以下代码:
- #include <iostream>
- using namespace std;
- int main(void)
- {
- int a = 0;
- int &r = a;
- r = 1;
- cout << "The value is: " << a << endl;
- return 0;
- }
这只是一个简单的例子,来说明引用的基本特性。下面将切入正题,解开引用的神秘面纱:
- #include <iostream>
- using namespace std;
- void MagicSummon(int* &rp)
- {
- int *p = rp;
- cout << "The content is: " << *p << endl;
- p = NULL;
- rp = p;
- }
- int main(void)
- {
- int a = 10;
- int *p = &a;
- MagicSummon(p);
- cout << "The value of the pointer is: " << p << endl;
- return 0;
- }
对于引用,我们可以将它理解为作为被引用变量的别名——比如:int &r = a; 当你在使用引用r时,你可以将它想象为正在使用a,也就是说对r进行操作与对a进行操作没有本质上的区别。为了能实现这个语义,如果现在把r看作为存在实体的变量,那么它在扮演左值与扮演右值时具有相同的操作。这似乎看起来不是很明显。
在上述例子中使用了对指针变量的引用,更能看清事实真相。我们现在假设参数rp是一个实体(有为它分配存储地址的),然后用以下代码来做个对比:
- #include <iostream>
- using namespace std;
- void MagicSummon(int** pp)
- {
- int *p = *pp;
- cout << "The content is: " << *p << endl;
- p = NULL;
- *pp = p;
- }
- int main(void)
- {
- int a = 10;
- int *p = &a;
- MagicSummon(&p);
- cout << "The value of the pointer is: " << p << endl;
- return 0;
- }
可以看出,在C++中,定义一个变量的引用可以实现为定义一个指向该变量的指针,然后总是以解引用(取内容)的操作使用该指针。
比如:int &r = a; r = 0; int b = r ==> int *p = &a; *p = 0; int b = *p;
int* &rp = p; rp = NULL; int *q = rp; ==> int **pp = &p; *pp = NULL; int *q = *pp;
这个显然与Java和C#中的引用功能不同。所以在C++中做一个交换值的函数比在Java和C#中要方便得多。