臨時對象是無名稱的非堆對象,由編譯器隱式創建,通常為 const。區別於局部變量:代碼中可見名稱的變量皆非臨時對象。
當實參類型與形參不匹配,但存在轉換構造函數時:
void func(const string& s);
func("hello"); // const char* -> string 臨時對象 -> 綁定引用
編譯器調用 string(const char*) 創建臨時 string,再綁定到 const string&。
函數參數為非引用類型時,實參會被拷貝構造為臨時對象:
void foo(MyClass obj); // 形參為值 MyClass a; foo(a); // 調用拷貝構造創建臨時對象 obj
函數返回非引用類型,返回語句會創建臨時對象作為返回值:
MyClass bar() { return MyClass(10); } // 返回臨時對象
MyClass c = bar(); // 再次拷貝(可能被 RVO 優化)
const T& ref = temporary; 臨時對象生命延長至引用生命結束。T obj = temporary; 臨時對象存活至拷貝/移動構造完成(C++17 起保證拷貝消除,直接構造)。func(string("hello")) 明確意圖,便於編譯器優化。T obj = val;(初始化)優於 T obj; obj = val;(默認構造 + 賦值 + 銷毀臨時對象)。class Big {
vector data;
public:
Big(int n) : data(n) {} // 昂貴構造
Big(const Big&) = default; // 昂貴拷貝
Big(Big&&) noexcept = default; // 廉價移動
Big& operator=(Big&&) noexcept = default;
};
Big make_big(int n) { return Big(n); } // NRVO:直接在調用處構造
void process(const Big& b); // 引用參數,無臨時對象
int main() {
process(Big(1000)); // 臨時對象綁定 const&,生命延長至語句結束
Big b = make_big(1000); // NRVO,零拷貝
Big c = std::move(b); // 移動,廉價
}
掌握臨時對象機制,是寫出高性能、正確 C++ 代碼的關鍵基石。