2013-03-17 71 views
4

這實際上是關於交換兩個引用的一個壞主意。這些參考資料不應該是可重置的,所以它不應該是可能的。我知道的很多。一種在C++中交換兩個引用的方法

我想要做什麼,是交換兩個引用,在某種程度上人們會交換兩個指針:地址被交換不是數據。假設:

int a = 0, b = 1; 
int *pA = &a, *pB = &b; 
std::swap(pA, pB); 

現在* Pa爲1和* PB爲0,但仍然是0,b是1還是然而這是不可能用引用:

int a = 0, b = 1; 
int &rA = a, &rB = b; 
std::swap(pA, pB); 

現在引用被交換,但原始值也被交換。我能想到的唯一的事情是這樣的:

template <class _Ty> 
struct resetable_ref { 
    _Ty &ref; 

    inline resetable_ref(resetable_ref &r) 
     :ref(r.ref) 
    {} 

    inline resetable_ref(_Ty &_ref) 
     :ref(_ref) 
    {} 

    inline resetable_ref &operator =(resetable_ref &r) 
    { 
     if(sizeof(resetable_ref) == sizeof(void*)) // compile-time constant (true) 
      *reinterpret_cast<void**>(this) = *reinterpret_cast<void**>(&r); 
     else 
      memcpy(this, &r, sizeof(resetable_ref)); // optimized away as dead code 
     return *this; 
    } 

    inline operator _Ty &() 
    { 
     return ref; 
    } 
}; 

int a = 0, b = 1; 
resetable_ref<int> rrA(a), rrB(b); 
std::swap(rrA, rrB); 

現在仍然是0和B仍然是1,內部RRA和無線電規則委員會中的引用交換。可惜,如果沒有醜陋的操作符=(),它就無法工作。至少它在MSVC中適用於我,不知道g ++是否會接受它(但我想它應該)。

整個引用交換應該用在一個對象中,該對象使用內部引用另一個對象的方式構建,並且我想爲它們創建一個swap()函數。我想避免使用指針,因爲引用的非空值特性非常好。這也將是一個更好的設計(resetable_ref本身除外)。

有沒有人有更好的想法如何去呢?任何人都可以想到一些兼容性/未定義的行爲問題?

我編寫了大部分代碼而沒有編譯,如果您發現某些錯誤,請耐心等待。

編輯:在我看來,很多人都忽略了這個問題的重點。我知道如何使用指針,甚至是如何在漂亮的模板中包裝指針。這個問題被標記爲「hack」,這是預期的。不要告訴我像「不這樣做,使用指針」的東西,因爲這不是我問的。如果你不喜歡這個話題,不要回答,但不要因爲你會使用指針而降低問題的質量。

+1

我想'的std :: reference_wrapper'可以工作。雖然從未真正使用它。 – chris 2013-03-17 16:44:00

+4

爲什麼不在你的類中使用一個指針而不是一個引用,使它成爲私有的,然後提供合適的成員函數來充當底層'int'的訪問器?這樣,您可以避免所有令人討厭的reinterpret_cast /潛在未定義行爲問題。 – 2013-03-17 16:45:39

+0

@chris謝謝,我不知道存在 – 2013-03-17 16:48:19

回答

3

一個可變引用是...不再是一個指針,你需要像引用那樣的隱式解引用。

template<class T> 
class mutable_ref 
{ 
public: 
    mutable_ref(T& t) :p(&t) 
    {} 

    operator T&() { return *p; } 
    operator const T&() const { return *p; } 

    void swap(mutable_ref& s) 
    { std::swap(p,s.p); } 

private: 
    T* p; 
}; 

// just in case you also want to specialize std::swap for mutable_ref. 
// not necessary, since the generic std::swap<T> use twice =, that is available. 
namespace std 
{ 
    template<class T> 
    void swap(mutable_ref<T>& a, mutable_ref<T>& b) 
    { a.swap(b); } 
} 

注意缺少缺省構造函數中,有一個初始化構造函數取一個參考,這使得該類不是空的。

唯一的問題是,要訪問最終的T成員,是「。」操作員,不可覆蓋,您需要爲此目的選擇一些東西。

簡單的就是使用*和 - >爲...

T* operator->() const { return p; } 
T& operator*() const { return *p; } 

裏面mutable_ref定義申述

+0

噢,我知道C++,我知道這可以做到。問題是如何交換引用。感謝您的回覆,這是很好的代碼。 – 2013-03-17 20:23:31

+0

問題是......它無法完成。這就是爲什麼我發佈了一個「不完美的解決方法」,它只是定義了一個「mutable_reference」,不存在於C++核心語言中。 – 2013-03-18 08:27:16

+1

但我認爲它是存在的:stdlib是「核心語言」的一部分,而stdlib包含'std :: reference_wrapper'。正如你所暗示的那樣,由於缺少'operator.',現在用戶必須編寫'refwrap.get()。member' - 但是希望Bjarne和co下一次將'operator.'帶入語言中; ) – 2016-09-18 16:33:09

相關問題