c++ 臨時變數問題?
#include &
#include &
using namespace std;const string Func()
{
return "123";
}int main()
{
string s = Func();cout &<&< s &<&< endl; return 0; }
const 引用不是會提升臨時變數的生命期嗎? 為什麼返回函數內的臨時變數會報錯了? 我對const引用的理解哪裡錯了嗎?
#include &
#include &
using namespace std;const string Func(const string s)
{
return s;
}int main()
{
string s = Func("123");cout &<&< s &<&< endl; return 0; }
但是這段代碼就可以了。 Func函數參數綁定到一個臨時變數,然後返回這個臨時變數的const引用,就沒有問題?
why?
「const 引用不是會提升臨時變數的生命期嗎?」說的是這種情況:
string bitch()
{
return "shit";
}
int main()
{
const string fuck = bitch();
return 0;
}
你第一個代碼其實是這樣
const string Func()
{
string tmp = "123";
return tmp;
//tmp這裡被析構了
}
const引用提升生命期,是將臨時變數的「在full expression結束銷毀」提升為
「在const引用生命結束銷毀」,而不是你這個例子的情況,
正確的適用情況 @vczh 舉了
首先你要明白引用不是一個對象,而是綁定對象的別名。在你第一個例子中的
const string Func()
{
return "123";
}
可以理解為
const string Func()
{
const string temp = "123";
return temp;
}
在func()函數結束時,臨時對象temp已經銷毀了,綁定temp的引用就不能用了。
而第二個例子
const string Func(const string s)
{
return s;
}int main()
{
string s = Func("123");
cout &<&< s &<&< endl; return 0; }
可以理解為
int main()
{
const string temp = "123";
string s = Func(temp);
cout &<&< s &<&< endl;
return 0;
}
臨時對象temp的作用域是整個main()函數。
《C++ Primer 第五版》中第二章中,關於引用和const的概念會有詳細介紹。引用不管理生命周期
誰告訴你可以返回局部自動變數的引用了返回引用一般是返回類成員的引用 全局變數的引用 堆上內容的引用而且你這裡多此一舉 返回左值引用後又通過拷貝構造構造一個新的string正確做法:class Foo
{
public:
auto getName() const
{
return name;
}
private:
std::string name;
};
Foo f;
auto name = f.getName();
@vczh
解釋一下輪子哥的代碼:
本質也不是引用管理了生命周期
只不過調用返回值類型的函數時本身就創建了一個匿名對象(c++11中所有作為值類型返回的類型必須有可訪問的移動構造函數,因為從返回值到匿名對象需要調用移動構造函數)引用只是將其具名化匿名對象沒被具名化時的生命周期是編譯器決定的
因為沒具名化之前 代碼中只可能去訪問到一次匿名對象所以一般編譯器會選擇立刻釋放(或者索性不創建匿名對象 這就是RVO)不過其實立刻釋放還是等到函數結束一起釋放都可以所以匿名對象也可以一直存在到函數結束 只是你再也看不到它而已既然你看不到了 編譯器就有權利"偷偷摸摸"把它優化了
具名化之後 就等於告訴編譯器 我給這個匿名對象命名了
編譯器就不能偷偷摸摸的因為我看不到它了就把它"優化"了不過引用也不會管理這個匿名對象的生命周期
舉個例子如果一個編譯器 決定在函數結束時才釋放所有自動變數 包括匿名對象那麼你給一個匿名對象具名化了然後把這個引用放到一個block里這個block結束後這個雖然引用就看不到了不過匿名對象並不會釋放
仍舊只會在函數末尾釋放所以引用並不管理生命周期(無論是具名對象還是匿名對象的生命周期都不歸引用管理)對匿名對象的引用只是標示了其的可見性 匿名對象的到底什麼時候死還是看編譯器返回引用是常見的C++誤用. 首先const引用並沒有改變臨時變數有效期的作用, 所以返回後引用對象被銷毀導致報錯. 其次即使對於非臨時變數, 返回引用的用法也不好界定, 要麼什麼作用也沒有, 比如你的第二段代碼, 要麼導致變數所屬權模糊, 引發維護性問題. 所以基本上, 除非你十分確定自己想要這種寫法, 比如說實現move語義, 否則盡量避免返回引用.
看大家幾小時這麼多回復, 不禁感慨輪子哥的魅力, 咔咔.
說正題, 臨時變數也是C++說不清道不明的東西, 我大致理解為強行兼容C和OOP所帶來的混亂. 其中有個略神髓的xvalue概念, 再牽扯到右值引用, 真是凌亂. 其實最後這些東西多數都是用來做庫優化的.推薦閱讀:
※為什麼 Python 現在(2015年)越來越火了?
※想提高編程能力,請大家評價這種學習方法是否可取?
※考慮到未來人工智慧的發展,應該學習C++/C語言還是Python語言?
※大學理科生零基礎自學計算機和編程有哪些書籍和方法比較好?
※對於一個程序員來說,寫代碼用台式機好還是筆記本好?