對於by reference的函式形參的一些很容易錯的點:
阿新 • • 發佈:2021-01-09
技術標籤:C++
這一塊內容迷茫了很久一直不清楚,今天搞透作為記錄:
- 對於by reference的函式形參,如果確實該函式不會修改引用繫結的內容,就必須宣告為by reference to const,這裡是必須,不是建議,儘管在很多情況下並不會出問題,只是因為沒涉及到下面這些case:
- 先說結論:
宣告為by reference to const而不是by reference的作用如下:
1.使用const可以避免無意中修改資料的程式設計錯誤
2.使用const使函式能夠處理const和非const實參,否則將只能接受非const資料
3.使用const引用使函式能夠正確生成並使用臨時變數 - 前兩點很清楚了就不再贅述,下面示例是用於解釋第三點的
#include <iostream>
#include <string>
using namespace std;
class B{
public:
explicit B(string p = "lixu") : s(p){}
string s;
};
void f( B& b){
cout << b.s << endl;
}
int main() {
//1. 在這種情況下呼叫f,傳入f的是一個右值的B型別的臨時變數,如果f的形參不是const,就相當於將一個non-const的左值引用繫結到一個右值臨時變數
//上,但右值被不能修改,如果這一步可以通過的話,就可以通過non-const的左值引用去修改一個右值了,顯然這一步不能這樣。
//2. 但f的形參若宣告為const,就可以通過了,因為即使const左值引用繫結這個右值臨時變數,也不用擔心這個引用會去修改那個右值,因此可以通過。
f(B("haha"));
return 0;
}
如果f的形參處宣告為B& b,就會報錯:
- 上面示例中還有可以探討的點:
結論是:編譯器為我們執行一步隱式型別轉換;
由於B的建構函式宣告為explicit,但即使把explicit去掉,呼叫時仍然可能通不過
//因為字面值常量“haha”到string本身是non-explicit的,因此從“haha”到string是隱式型別轉換;
//如果把B的建構函式也宣告為non-explicit,那麼從string到B也是隱式型別轉換;
//因此從“haha”到B需要經過兩步隱式型別轉換,但編譯器只會為我們執行一步,這也顯示了一點,編譯器不會為我們做超出預期的太多隱式的事情;
f("haha");//錯誤;
//要想通過編譯,只需我們顯式完成其中一步即可
f(string("haha")); //正確:"haha"到string顯式轉換,string到B隱式轉換
f(B("haha")); //正確:"haha"到string隱式轉換,string到B顯式轉換