Si tengo esto:¿Cómo puedo cambiar la variable a la que se refiere una referencia de C++?
int a = 2;
int b = 4;
int &ref = a;
¿Cómo puedo hacer ref
referirse a b
después de este código?
Si tengo esto:¿Cómo puedo cambiar la variable a la que se refiere una referencia de C++?
int a = 2;
int b = 4;
int &ref = a;
¿Cómo puedo hacer ref
referirse a b
después de este código?
Esto no es posible, y eso es by design. Las referencias no pueden ser rebotadas.
No puede reasignar una referencia.
No puede reasignar una referencia, pero si está buscando algo que le proporcione capacidades similares, puede hacer un puntero en su lugar.
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.
Puede obtener o establecer el valor dentro del puntero con:
*ptr = 5; //set
int c = *ptr; //get
Estás redeclarando 'ptr'. –
Eso no es posible en la forma que desee. C++ simplemente no te permite volver a vincular a lo que apunta una referencia.
Sin embargo, si desea utilizar el engaño casi se puede simular con un nuevo campo de aplicación ( NUNCA hacer esto en un programa real):
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.
}
casi -1 digno – ThomasMcLeod
con C++ 11 está el nuevo (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);
}
Esto también es útil para almacenar referencias en contenedores.
A pesar de su mala idea, ya que contradice el objetivo de la utilización de referencias, es posible cambiar la referencia directa
const_cast< int& >(ref)=b;
Es curioso cómo las personas +1 solución equivocada. Este código cambiará la variable a la que hace referencia el punto de referencia, no se refiere a sí mismo – Slava
Ya no me sorprende en los sitios de Exchange: D – GameDeveloper
Oye, esta es claramente una respuesta incorrecta. @visu, por favor quítalo. – einpoklum
Se puede hacer una envoltura de referencia muy fácil usando la colocación de nuevo:
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
Esta respuesta es mucho más complicada de lo necesario; la pregunta era muy simple y podía responderse con un solo mensaje. – lukelazarovic
Esto es posible. Porque debajo del capó, la referencia es un puntero. El código siguiente imprimirá "hola mundo"
#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());
}
Cualquier efecto que tengas en UB no significa que "funciona" – Slava
@Slava: ¿Es realmente un comportamiento indefinido? ¿Es una referencia no definida como un "puntero disfrazado", por así decirlo? – einpoklum
'otherVariable' no es requerido usando' * ((uintptr_t *) this) = ((uintptr_t) & str) 'en' setRef' – joas
Formalmente hablando, eso es imposible, ya que está prohibido por diseño. Arbitrariamente hablando, eso es posible.
Las referencias se almacenan como un puntero, por lo que siempre puede cambiar a dónde apunta siempre y cuando sepa cómo obtener su dirección. Del mismo modo, también puede cambiar el valor de las variables de const, las variables de miembros de const o incluso las variables de miembros privados cuando no tiene acceso.
Por ejemplo, el siguiente código de referencia ha cambiado const miembro privado de la clase A: salida
#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;
}
Programa:
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
Como se puede ver que un .i1 apunta inicialmente a i, después del cambio, apunta a j.
Sin embargo, hacerlo es considerado como peligroso y, por lo tanto, no recomendado, ya que anula el objetivo original de encapsulación de datos y OOP. Es más parecido a la piratería de direcciones de memoria.
En el siguiente código, estoy cambiando la referencia de x a k y sigo obteniendo el resultado. ¿Puedes decirme cómo es esto posible? int a = 50; int &x=a; int k = 10; cout << x << endl; x = k; cout << x << endl; – Rajesh
No está cambiando la referencia, está asignando el valor de 'k' al objeto al que hace referencia' x'. Después de esta asignación, 'a == k', y' x' todavía se refiere a 'a'. –