C++的this指標和引用符號的搭配使用理解
看到一個C++視訊教程裡關於this指標講解的時候多次用到了引用,老師的程式碼如下:
class Person { public: Person(int age) { this -> age = age; } Person& PersonAddAge(Person &p) { this->age += p.age; //把別人的age加到自己上面 //this指向p2的指標,而*this指向的是p2這個物件的本體 return *this; } int age; }; void test01() { Person p1(10); Person p2(10); p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1); cout<<"p2的年齡為:"<<p2.age<<endl; } int main() { test01(); system("pause"); return 0; }
其執行結果為:p2的年齡為:40
我關注的是其中的下面這行程式碼裡為什麼需要這兩個引用符號,因為*this已經可以表示指向原物件了,那為啥要多次一舉呢?
首先第二個引用符號在這裡是不需要的(老師的附屬檔案裡也沒有第二個引用符號,可能講的時候沒注意),放在這裡不算錯只是引用的作用是讓被引用變數的值一起改變,而我們這裡被引用變數的值是用來加到前面的,沒有改變其值,所以這個引用符號可以去掉。
那第一個引用符號又是為何呢?為了說明清楚,我們將增加幾行程式碼,讓諸位更加看清this的本質(去掉了引用符號,且每次輸出age值)
class Person { public: Person(int age) { this -> age = age; } Person PersonAddAge(Person p) { this->age += p.age; //把別人的age加到自己上面 //this指向p2的指標,而*this指向的是p2這個物件的本體 cout<< (*this).age<<endl;// return *this; } int age; }; void test01() { Person p1(10); Person p2(10); cout<<p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1).age<<endl;// cout<<"p2的年齡為:"<<p2.age<<endl; } int main() { test01(); system("pause"); return 0; }
發現不加引用符號,雖然最終結果是40,但是p2的age值只是加了一次,即相當於三次呼叫函式中只有第一次指向的是原物件p2,其原因是不加引用符號,那麼return的結果只是將*this指向的物件複製給一個臨時物件,而不是真正的原物件。就好比普通函式中return x,返回的只是x的複製的值。即這裡只有第一次函式內部對原物件p2進行了修改,而後面每次呼叫都是對臨時物件操作的。那麼如果加上引用符號&之後,就使得每次的臨時物件是原物件p2的一個別名,即每次呼叫函式都改變了原物件p2內的引數。
這才有了老師附的如下完整程式碼:
class Person { public: Person(int age) { //1、當形參和成員變數同名時,可用this指標來區分 this->age = age;//this指標指向被呼叫的成員函式所屬的物件。 } Person& PersonAddPerson(Person p) { this->age += p.age; //返回物件本身 return *this; } int age; }; void test01() { Person p1(10); cout << "p1.age = " << p1.age << endl; Person p2(10); p2.PersonAddPerson(p1).PersonAddPerson(p1).PersonAddPerson(p1); cout << "p2.age = " << p2.age << endl; } int main() { test01(); system("pause"); return 0; }
自結:要加引用符號return的才是真正的P2物件本身,否則只是P2的一個copy。即如果沒有&,那麼後面操作就不會改變P2了
補充:原來老師視訊的最後講了這個哈哈哈哈,我看到一半的時候因為老師直接加了&導致我不理解就自己摸索原理去了,同時寫了上面的文章,寫完了繼續看視訊的時候發現老師有講,原因是:以值的方式返回區域性物件會呼叫拷貝建構函式,從而生成新的匿名變數。和我上面理解的差不多,也就是不加引用的話是p2`,p2``……,總之p2的屬性值就不會變了。
其實一句話要想實現這種鏈式程式設計,記住加&就行了。