Se ho questo:Come posso modificare la variabile a cui fa riferimento un riferimento C++?
int a = 2;
int b = 4;
int &ref = a;
Come posso fare riferimento a ref
b
dopo questo codice?
Se ho questo:Come posso modificare la variabile a cui fa riferimento un riferimento C++?
int a = 2;
int b = 4;
int &ref = a;
Come posso fare riferimento a ref
b
dopo questo codice?
Questo non è possibile, e questo è by design. I riferimenti non possono essere rimbalzi.
Non è possibile riassegnare un riferimento.
Non è possibile riassegnare un riferimento, ma se si sta cercando qualcosa che fornirebbe capacità simili a questo, si può invece fare un puntatore.
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.
È possibile ottenere o impostare il valore all'interno del puntatore con:
*ptr = 5; //set
int c = *ptr; //get
Stai redecando 'ptr'. –
Questo non è possibile nel modo desiderato. C++ non ti permette di ricollegare ciò a cui fa riferimento un riferimento.
Tuttavia, se si desidera utilizzare l'inganno si può quasi simulare con un nuovo ambito (MAI fare questo in un programma vero e proprio):
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.
}
quasi -1 degno – ThomasMcLeod
Con C++ 11 c'è il nuovo (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);
}
Questo è anche utile per la memorizzazione di riferimenti in contenitori.
Anche se la sua è una cattiva idea in quanto contrasta con l'obiettivo di utilizzare riferimenti, è possibile modificare il riferimento direttamente
const_cast< int& >(ref)=b;
È divertente come le persone fanno +1 alla soluzione sbagliata. Questo codice cambierà la variabile in cui i punti di riferimento non si riferiscono allo stesso – Slava
Nulla mi sorprende più sui siti di Exchange: D – GameDeveloper
Ehi, questa è chiaramente una risposta sbagliata. @visu, per favore rimuovilo. – einpoklum
Si può fare un involucro di riferimento molto semplice utilizzando la nuova collocazione:
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
Questa risposta è molto più complicata del necessario: la domanda era molto semplice e si poteva rispondere con un solo liner. – lukelazarovic
Questo è possibile. Perché sotto il cappuccio, il riferimento è un puntatore. Il seguente codice stamperà "ciao mondo"
#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());
}
Qualsiasi effetto tu abbia su UB non significa che "funzioni" – Slava
@Slava: è in realtà un comportamento non definito? Un riferimento non definito per essere un "puntatore travestito", per così dire? – einpoklum
'otherVariable' non è richiesto usando' * ((uintptr_t *) this) = ((uintptr_t) & str) 'in' setRef' – joas
Formalmente, che è impossibile in quanto è vietato in base alla progettazione. Arbitrariamente parlando, è possibile.
Un riferimento è memorizzato come puntatore, in modo da poter sempre cambiare dove punta fino a quando si sa come ottenere il suo indirizzo. Allo stesso modo, puoi anche cambiare il valore delle variabili const, delle variabili membro const o anche delle variabili membro private quando non hai accesso.
Ad esempio, il seguente codice di riferimento è cambiato const membro privato della classe di A: uscita
#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;
}
Programma:
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
Come si può vedere che a.i1 inizialmente punta a i, dopo la modifica, punta a j.
Tuttavia, fare questo è considerato pericoloso e quindi non raccomandato, in quanto sconfigge lo scopo originale di incapsulamento dei dati e OOP. È più come l'hacking degli indirizzi di memoria.
Nel codice seguente, sto cambiando il riferimento di x a k e sto ancora ottenendo il risultato. Puoi dirmi come è possibile? int a = 50; int &x=a; int k = 10; cout << x << endl; x = k; cout << x << endl; – Rajesh
Non stai cambiando il riferimento, stai assegnando il valore di 'k' all'oggetto a cui si riferisce' x'. Dopo questo compito, 'a == k', e' x' si riferisce ancora a 'a'. –