2011-10-10 40 views

回答

61

這是不可能的,那就是by design。參考資料不能被反彈。

+0

在下面的代碼中,我將x的引用更改爲k並仍然得到結果。你能告訴我這有可能嗎? int a = 50; int &x=a; int k = 10; cout << x << endl; x = k; cout << x << endl; – Rajesh

+1

您並未更改參考,您正在將'k'的值分配給'x'所指的對象。在這個賦值之後,'a == k'和'x'仍然指向'a'。 –

7

您不能重新分配參考。

16

你不能重新分配引用,但是如果你正在尋找能夠提供類似功能的東西,你可以改爲使用指針。

int a = 2; 
int b = 4; 
int* ptr = &a; //ptr points to memory location of a. 
ptr = &b;  //ptr points to memory location of b now. 

你可以得到或指針內設置的值: 

*ptr = 5;  //set 
int c = *ptr; //get 
+3

您正在重新聲明'ptr'。 –

7

這是不可能的,你想要的方式。 C++不會讓你重新引用參考指向的內容。

但是,如果你要使用欺騙,你幾乎可以以新的範疇(NEVER在實際的程序中做到這一點),模擬它:

int a = 2; 
int b = 4; 
int &ref = a; 

{ 
    int& ref = b; // Shadows the original ref so everything inside this { } refers to `ref` as `b` now. 
} 
+4

幾乎-1值得 – ThomasMcLeod

48

用C++ 11有新的(ISH )std::reference_wrapper

#include <functional> 

int main() { 
    int a = 2; 
    int b = 4; 
    auto ref = std::ref(a); 
    //std::reference_wrapper<int> ref = std::ref(a); <- Or with the type specified 
    ref = std::ref(b); 
} 

這對於在容器中存儲引用也很有用。

0

雖然它的,因爲它違背了使用引用的目的,一個壞主意,有可能使用放置新更改參考直接

const_cast< int& >(ref)=b; 
+7

人們+1錯誤的解決方案很有趣。這段代碼將會改變ref引用的地方,而不是引用自身 – Slava

+0

在Exchange站點上我再也沒有看到:D – GameDeveloper

+0

嘿,這顯然是一個錯誤的答案。 @visu,請刪除它。 – einpoklum

3

你可以做一個參考的包裝非常簡單:

template< class T > 
class RefWrapper 
{ 
public: 
    RefWrapper(T& v) : m_v(v){} 

    operator T&(){ return m_v; } 
    T& operator=(const T& a){ m_v = a; return m_v;} 
    //...... // 
    void remap(T& v) 
    { 
     //re-map reference 
     new (this) RefWrapper(v); 
    } 

private: 
    T& m_v; 
}; 


int32 a = 0; 
int32 b = 0; 
RefWrapper<int> r(a); 

r = 1; // a = 1 now 
r.remap(b); 
r = 2; // b = 2 now 
+2

這個答案比必要的複雜得多 - 問題非常簡單,可以用一行代碼來回答。 – lukelazarovic

3

這是可能的。因爲在引擎蓋下,引用是一個指針。 下面的代碼將打印的「Hello World」

#include "stdlib.h" 
#include "stdio.h" 
#include <string> 

using namespace std; 

class ReferenceChange 
{ 
public: 
    size_t otherVariable; 
    string& ref; 

    ReferenceChange() : ref(*((string*)NULL)) {} 

    void setRef(string& str) { 
     *(&this->otherVariable + 1) = (size_t)&str; 
    } 
}; 

void main() 
{ 
    string a("hello"); 
    string b("world"); 

    ReferenceChange rc; 

    rc.setRef(a); 
    printf("%s ", rc.ref.c_str()); 

    rc.setRef(b); 
    printf("%s\n", rc.ref.c_str()); 
} 
+0

無論你對UB有什麼影響並不意味着它「有效」 – Slava

+0

@Slava:它實際上是不確定的行爲嗎?沒有把參考定義爲「僞裝指針」,可以這麼說嗎? – einpoklum

+0

'setVeriable'不需要在'setRef'中使用'*((uintptr_t *)this)=((uintptr_t)&str)'' – joas

4

從形式上來講,這是不可能的,因爲它被設計禁止。任意說,這是可能的。

引用存儲爲指針,所以只要知道如何獲取地址,就可以隨時更改它指向的位置。同樣,如果您無權訪問,也可以更改常量變量,常量成員變量甚至私有成員變量的值。

例如,下面的代碼已經改變了A級的常量私有成員參考:

#include <iostream> 
using namespace std; 

class A{ 
private: 
    const int &i1; 
public: 
    A(int &a):i1(a){} 
    int geti(){return i1;} 
    int *getip(){return (int*)&i1;} 
}; 

int main(int argc, char *argv[]){ 
    int i=5, j=10; 
    A a(i); 
    cout << "before change:" << endl; 
    cout << "&a.i1=" << a.getip() << " &i=" << &i << " &j="<< &j << endl; 
    cout << "i=" << i << " j=" <<j<< " a.i1=" << a.geti() << endl; 
    i=6; cout << "setting i to 6" << endl; 
    cout << "i=" << i << " j=" <<j<< " a.i1=" << a.geti() << endl; 

    *(int**)&a = &j; // the key step that changes A's member reference 

    cout << endl << "after change:" << endl; 
    cout << "&a.i1=" << a.getip() << " &i=" << &i << " &j="<< &j << endl; 
    cout << "i=" << i << " j=" <<j<< " a.i1=" << a.geti() << endl; 
    j=11; cout << "setting j to 11" << endl; 
    cout << "i=" << i << " j=" <<j<< " a.i1=" << a.geti() << endl; 
    return 0; 
} 

程序輸出:

before change: 
&a.i1=0x7fff1b624140 &i=0x7fff1b624140 &j=0x7fff1b624150 
i=5 j=10 a.i1=5 
setting i to 6 
i=6 j=10 a.i1=6 

after change: 
&a.i1=0x7fff1b624150 &i=0x7fff1b624140 &j=0x7fff1b624150 
i=6 j=10 a.i1=10 
setting j to 11 
i=6 j=11 a.i1=11 

正如你可以看到,一個。i1最初指向i,更改後指向j

但是,這樣做被認爲是危險的,因此不予推薦,因爲它破壞了數據封裝和OOP的原始目的。這更像是內存地址黑客行爲。