如何理解C++ 臨時變數的常量性
1.認識臨時變數的常量性
關於臨時變數的常量性,先看一段程式碼。
void print(string& str) { cout<<str<<endl; } //如此呼叫會報編譯錯誤 print("hello world");
在Linux環境使用g++編譯,會出現: invalid initialization of non-const reference of type ‘std::string&' from a temporary of type 'std::string'的錯誤。其中文意思為臨時變數無法為非const引用初始化。出錯的原因是編譯器根據字串"hello world"構造一個string型別的臨時物件,這個臨時變數具有const屬性,當這個臨時變數傳遞給非const的string&引用型別時,無法隱式完成const到非const的型別轉換,便出現上面的編譯錯誤。解決辦法是將print()函式的引數改為常引用。程式碼修改如下,可順利通過編譯。
void print(const string& str) { cout<<str<<endl; } //順利通過編譯 print("hello world");
通過以上程式碼,可以看出在設計函式時,形參儘可能地使用const,這樣可以使程式碼更為健壯,將錯誤暴露於編譯階段。
2.臨時變數常量性的原因
為什麼臨時物件作為引用引數傳遞時,形參必須是常量引用呢?很多人對此的解釋是臨時變數是常量,不允許賦值改動,所以作為非常量引用傳遞時,編譯器就會報錯。這個解釋在理解臨時變數不能作為非const引用引數這個問題上是可以的,但不夠準確。事實上,臨時變數是可以作為左值(Lvalue) 並被賦值的,請看下面的程式碼:
class IntClass { private: int x; public: IntClass(int value):x(value){} friend ostream& operator<<(ostream &os,const IntClass &intc); }; //過載operator<< ostream& operator<<(ostream &os,const IntClass &intc) { os<<intc.x; return os; } int main(int argc,char* argv[]) { cout << (IntClass(6) = IntClass(8))<<endl; }
程式輸出:
8
以上程式碼正確編譯執行,沒有錯誤。IntClass(6)表示生成一個無名臨時變數並作為左值被修改,所以臨時變數並不是常量,只是編譯器從語義層面限制了臨時變數傳遞給非const引用。注意,這裡與《C++程式設計思想》在第八章中的“臨時量”小節中認為“編譯器使所有的臨時量自動設為const”的說法有些不同。
那編譯器為何作出如此限制呢?如果一個實參以非const引用傳入函式,編譯器有理由認為該實參會在函式中被修改,並且這個被修改的引用在函式返回後要發揮作用。但如果把一個臨時變數當作非const引用引數傳進來,由於臨時變數的特殊性,臨時變數所在的表示式執行結束後,臨時變數就會被釋放,所以,一般說來, 修改一個臨時變數是毫無意義的,據此,C++編譯器加入了臨時變數不能作為非const引用實參這個語義限制,意在限制這個非常規用法的潛在錯誤。
以上就是如何理解C++ 臨時變數的常量性的詳細內容,更多關於C++ 臨時變數的常量性的資料請關注我們其它相關文章!