C++中“非常量引用的初始值必須是左值”的處理方法

轉自:https://blog.csdn.net/hy13684802853/article/details/87251736#commentBox

1 左值和右值
在C++中,左值可以出現在賦值語句的左邊和右邊;右值只能出現在賦值語句的右邊,不能出現在賦值語句的左邊。變量是左值,常量是右值。

2 引用
引用(reference)爲對象起了另外一個名字,引用類型引用(refers to)另外一種類型。通過在變量名前添加“&”符號來定義。引用具體的使用方法請參考《C++的引用與重載函數》。

3 非常量引用的初始值必須是左值
3.1 產生原因
自定義函數increment()的代碼爲

void increment(double& x)
 
{
 
x += 1.0;
 
}

在調用該函數時,有如下代碼

increment(5);

因爲increment()函數的形參是double&,而調用時的實參是整形常量。因此,在調用increment()函數時實際上存在一個隱式的類型轉換

double& temp = (double)5;
 
x = temp;

假設此後在increment()中對形參x進行修改,實際上就是對常量進行了修改,這顯然是不能允許的。所以,在對非常量進行初始化時,該初始值必須是左值,而不能是右值。因此,會顯示“非常量引用的初始值必須是左值”的錯誤信息。

3.2 解決方法
有兩種方法可以解決以上問題,一是避免隱式轉換;二是避免修改形參。

3.2.1 避免隱式轉換
可以使用如下方法避免隱式轉換

double i = 5.0l;
 
increment(i);

避免了隱式轉換,也就是避免了對非常量引用的初始化。

3.2.2 避免修改形參
將increment()函數的形參類型修改爲const double&,則在進行隱式轉換時就可以用常量(右值)對其進行初始化了。

void increment(const double& x)
 
{
 
}

需要注意的時,因爲此時形參x的值是常量,所以在increment()函數內部中不能對其進行修改。

4 實戰
在CSDN論壇中有朋友提到如下問題

定義了一個Time類,重載cout輸出time類時報錯,其報錯的信息即爲“非常量引用的初始值必須是左值”。


ostream &  operator <<(ostream& os,Time& _t)
{
os<<_t.hour<<':'<<_t.minute<<':'<<_t.second<<endl;
 
return& os;
}


在《C++函數的返回值(上)》“當函數的返回值是非引用變量時,會用一個臨時變量來保存該返回值;當函數的返回值是引用變量時,不使用臨時變量,直接返回該引用”。
因爲其重載的<<操作符的返回值是一個引用變量,因此不存在“3 非常量引用的初始值必須是左值”中提到的臨時變量隱式轉換的問題。該操作符return的是&os,其含義是os的地址,該地址是一個常量,即右值;而操作符返回值是一個非常量的引用,因此會產生“非常量引用的初始值必須是左值”的報錯信息。

修改的方法爲將重載的<<操作符的return改爲

return os;

即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章