3.1.3 引用返回值
引用表达式是一个左值表达式,因此它可以出现在形参和实参的任何一方。若一个函数返回了引用,那么该函数的调用也可以被赋值。普通函数返回值时,要生成一个值的副本。而引用返回值时,不生成值的副本。
例如,有以下程序:
- #include <iostream.h>
- int n=0;
- int & f(int m)
- { n+=m;
- return n;
- }
- void main()
- { f(10)+=20;
- cout << "n=" << n << endl;
- }
上述程序中,由于f函数返回全局变量n的引用,所以可以作为左值直接进行"+="运算。f(10) += 20等价于n = n + 20 = 10 + 20 = 30。其执行结果如下:
- n=30
并不是所有函数都可以返回引用。一般地,当返回值不是本函数的局部变量时可以返回一个引用;否则,当函数返回时,该引用的变量就会被自动释放,所以对它的任何引用都将是非法的。在通常的情况下,引用返回值只用在需要对函数的调用重新赋值的场合,也就是对函数的返回值重新赋值的时候。
例如,有以下程序:
- #include <iostream.h>
- #include <string.h>
- class MyClass
- { char *pstr;
- int size;
- public:
- MyClass() {} //默认构造函数
- MyClass(char a[],int n) //重载构造函数
- { pstr=new char[n+1]; //分配n+1个字符空间
- strcpy(pstr,a); //复制字符串
- size=n;
- }
- ~MyClass() //析构函数
- { delete [] pstr; }
- MyClass Copy(MyClass &obj) //复制
- { this->pstr=new char[obj.size+1];
- strcpy(this->pstr,obj.pstr);
- this->size=obj.size;
- return *this; //返回当前对象,即用修改后的对象替代原对象
- }
- void Disp() //输出pstr
- { cout << pstr << endl; }
- };
- void main()
- { MyClass s("ABC",3),s1;
- cout << "s:"; s.Disp();
- s1.Copy(s);
- cout << "s1:"; s1.Disp();
- }
MyClass类中Copy成员函数用于将形参obj对象复制给当前调用的对象,并采用深复制。但在程序执行时出现错误。这是因为执行s1.Copy(s)时,this指针指向对象s1,通过this指针修改s1对象的pstr和size数据成员,当执行return *this时返回this所指对象,希望用它替换原来的s1对象,但由于没有采用引用,达不到希望的效果。
改正的方法十分简单,只需将Copy成员函数的返回类型改为MyClass对象引用即可,这样s1和返回对象共享同一内存空间。
引用返回值经常用于运算符重载中,这将在第5章中介绍。