C++11 引入的右值引用是革命性特性,解決了臨時物件無法修改、拷貝成本高昂的問題。本文探討如何在 C++03 環境下,透過轉換運算子與樣板技術模擬 std::move 與移動語意。
在 C++03 中,臨時物件(右值)只能綁定到 const T&,無法直接「偷取」其資源。若要實現 A = factory(B, C) 避免拷貝,必須取得臨時物件的修改權限。
將 operator=(const Array&) 設為 private 或移除,迫使編譯器尋找其他多載版本。
利用轉換運算子 operator rv<T>&() 將物件轉型為可修改的包裝型別 rv<T>。
rv<T>template <typename T>
class rv : public T {
public:
rv() {}
rv(const rv& rhs) {}
~rv() {}
void operator=(const rv& rhs) {}
};
繼承自 T,擁有完整存取權,零額外開銷。
在類別內定義:
operator rv<Array>&() 與 operator const rv<Array>&() constoperator=(const Array&) 重導至移動指派operator=(Array&)(左值拷貝)與 operator=(rv<Array>&)(右值移動)template <typename T>
inline rv<T>& move_emu(T& rhs) {
return *(static_cast<rv<T>*>(&rhs));
}
// const 版本:退回拷貝語意
template <typename T>
inline const T& move_emu(const T& rhs) {
return rhs;
}
// rv<T> 版本:直接返回
template <typename T>
inline rv<T>& move_emu(rv<T>& rhs) {
return rhs;
}
#define COPYABLE_AND_MOVABLE(TYPE) \
public: \
TYPE& operator=(TYPE& t) \
{ this->operator=(static_cast<const rv<TYPE>&>(const_cast<const TYPE&>(t))); return *this; } \
public: \
operator rv<TYPE>&() { return *static_cast<rv<TYPE>*>(this); } \
operator const rv<TYPE>&() const { return *static_cast<const rv<TYPE>*>(this); } \
private:
文中提供 integer 類別完整實作,展示移動建構、移動指派、move_emu 與 factory 函式的協同運作,輸出結果證明資源確實被「偷取」而非拷貝。