注:C++ 有三種傳遞方式:值傳遞,指針傳遞,引用傳遞
返回“值”和返回“引用”是不同的
函數返回值時會產生一個臨時變量作爲函數返回值的副本,而返回引用時不會產生值的副本,既然是引用,那引用誰呢?這個問題必須清楚,否則將無法理解返回引用到底是個什麼概念。以下是幾種引用情況:
一、千萬不要返回局部對象的引用
[cpp] view plain copy
- const string &mainip(const string &s)
- {
- string ret=s;
- return ret;
- }
當函數執行完畢,程序將釋放分配給局部對象的存儲空間。此時,對局部對象的引用就會指向不確定的內存。
同理,指針也是這樣,返回指針的時候,不能指向局部臨時變量,否則指針將變爲野指針;
二、引用函數的參數,當然該參數也是一個引用
[cpp] view plain copy
- const string &shorterString(const string &s1,const string &s2)
- {
- return s1.size()<s2.size()?s1:s2;
- }
以上函數的返回值是引用類型。無論返回s1或是s2,調用函數和返回結果時,都沒有拷貝這些string對象。簡單的說,返回的引用是函數的參數s1或s2,並且參數s1、s2也是引用,不是在函數體內產生的。函數體內局部對象是不能被引用的,因爲函數調用完局部對象會被釋放。
三、返回 this 指向的對象
在類的成員函數中,返回引用的類對象,當然不能是函數內定義的類對象(會釋放掉),一般爲 this 指向的對象,典型的例子是 string類的賦值函數。
[cpp] view plain copy
- String& String::operator =(const String &str) //注意與“+”比較,函數爲什麼要用引用呢?a=b=c,可以做爲左值
- {
- if (this == &str)
- {
- return *this;
- }
- delete [] m_string;
- int len = strlen(str.m_string);
- m_string = new char[len+1];
- strcpy(m_string,str.m_string);
- return *this;
- }
四、引用返回this 的成員變量,或者 引用參數的成員變量
原標題爲:引用返回左值(上例的=賦值也是如此,即a=b=c是可以的)
原文這裏表達不清晰,因爲只要是引用,都可以作爲左值使用。只因爲下面的例子一般用在等號左邊,當左值使用。
可以定義一個和返回值一樣的引用類型,來接受函數的返回值,操作此引用值,和直接操作函數的參數是一樣的,引用都是使用引用傳遞;
[cpp] view plain copy
- char &get_val(string &str,string::size_type ix)
- {
- return str[ix];
- }
- 使用語句調用:
- string s("123456");
- cout<<s<<endl;
- get_val(s,0)='a';
- cout<<s<<endl;
這種情況,和第二種是一樣的,只不過是返回了參數(引用類型)的一部分。也可以不作爲左值,故修改如下:
[cpp] view plain copy
- char &ch = get_val(s,0);
- ch = ‘A’;
此句進行的都是引用傳遞,故運行之後,s[0] 就變爲了 A,s爲“A23456”;
此外,可以返回引用參數的成員變量,親測有效。似乎不是局部臨時變量,只要函數結束之後內存沒有被銷燬的,作爲引用返回都沒問題:
[cpp] view plain copy
- QString& Test(Student &stu)
- {
- return stu.m_name;
- }
[cpp] view plain copy
- QString & Student::getRName()
- {
- return (*this).m_name;
- }
五、最後轉上一段code作爲總結
[cpp] view plain copy
- #include<iostream>
- using namespace std;
- string make_plural(size_t,const string&,const string&);
- const string &shorterString(const string &,const string &);
- const string &mainip(const string&);
- char &get_val(string &,string::size_type);
- int main(void)
- {
- cout<<make_plural(1,"dog","s")<<endl;
- cout<<make_plural(2,"dog","s")<<endl;
- string string1="1234";
- string string2="abc";
- cout<<shorterString(string1,string2)<<endl;
- cout<<mainip("jiajia")<<endl;
- string s("123456");
- cout<<s<<endl;
- get_val(s,0)='a';
- cout<<s<<endl;
- getchar();
- return 0;
- }
- //返回非引用
- string make_plural(size_t i,const string &word,const string &ending)
- {
- return (i==1)?word:word+ending;
- }
- //返回引用
- const string &shorterString(const string &s1,const string &s2)
- {
- return s1.size()<s2.size()?s1:s2;
- }
- //禁止返回局部對象的引用(我的dev c++ 沒有報錯,比較可怕)
- const string &mainip(const string &s)
- {
- string ret=s;
- return ret;
- }
- //引用返回左值
- char &get_val(string &str,string::size_type ix)
- {
- return str[ix];
- }