Wenn ich das habe:
int a = 2;
int b = 4;
int &ref = a;
Wie kann ich nach diesem Code darauf ref
verweisen b
?
Wenn ich das habe:
int a = 2;
int b = 4;
int &ref = a;
Wie kann ich nach diesem Code darauf ref
verweisen b
?
Dies ist nicht möglich, und das ist beabsichtigt . Referenzen können nicht zurückgebunden werden.
k
dem Objekt, auf das verwiesen wird, den Wert von zux
. Nach dieser Zuordnunga == k
undx
bezieht sich immer noch aufa
.In C ++ 11 gibt es den neuen (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); }
Dies ist auch nützlich, um Referenzen in Containern zu speichern.
quelle
Sie können eine Referenz nicht neu zuweisen, aber wenn Sie nach etwas suchen, das ähnliche Fähigkeiten bietet, können Sie stattdessen einen Zeiger verwenden.
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.
Sie können den Wert innerhalb des Zeigers abrufen oder festlegen mit:
*ptr = 5; //set int c = *ptr; //get
quelle
ptr
.Sie können eine Referenz nicht neu zuweisen.
quelle
Formal ist das unmöglich, da es vom Design her verboten ist. Das ist willkürlich möglich.
Eine Referenz wird als Zeiger gespeichert, sodass Sie jederzeit ändern können, wohin sie verweist, solange Sie wissen, wie Sie ihre Adresse erhalten. In ähnlicher Weise können Sie auch den Wert von const-Variablen, const-Mitgliedsvariablen oder sogar privaten Mitgliedsvariablen ändern, wenn Sie keinen Zugriff darauf haben.
Der folgende Code hat beispielsweise die Konstante für private Mitglieder der Klasse A geändert:
#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; }
Programmausgabe:
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
Wie Sie sehen können, zeigt a.i1 zunächst auf i , nach der Änderung auf j .
Dies wird jedoch als gefährlich und daher nicht empfohlen angesehen, da es den ursprünglichen Zweck der Datenkapselung und des OOP zunichte macht. Es ist eher wie das Hacken von Speicheradressen.
quelle
Das ist nicht so möglich, wie Sie es wollen. In C ++ können Sie einfach nicht erneut binden, auf was eine Referenz verweist.
Wenn Sie jedoch Tricks anwenden möchten, können Sie diese fast mit einem neuen Bereich simulieren ( tun Sie dies NIEMALS in einem echten Programm):
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. }
quelle
Mit der neuen Platzierung können Sie einen Referenz-Wrapper sehr einfach gestalten:
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
quelle
std::launder
. Sie hätten einfach einen Zeiger verwenden können.Das ist möglich. Denn unter der Haube ist Referenz ein Zeiger. Der folgende Code gibt "Hallo Welt" aus.
#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()); }
quelle
otherVariable
ist nicht erforderlich mit*((uintptr_t*)this) = ((uintptr_t)&str)
insetRef
Es ist unmöglich, wie andere Antworten besagen.
Wenn Sie Ihre Referenz jedoch in einem
class
oder speichernstruct
, können Sie das Ganze mithilfe der Platzierung neu neu erstellen, sodass die Referenz erneut gebunden wird. Vergessen Sie nicht, mit @HolyBlackCatstd::launder
auf das neu erstellte Objekt zuzugreifen, oder verwenden Sie den Zeiger, der von der neuen Platzierung zurückgegeben wurde. Betrachten Sie mein Beispiel:#include <iostream> struct A { A(int& ref) : ref(ref) {} // A reference stored as a field int& ref; }; int main() { int a = 42; int b = 43; // When instance is created, the reference is bound to a A ref_container(a); std::cout << "&ref_container.ref = " << &ref_container.ref << std::endl << "&a = " << &a << std::endl << std::endl; // Re-create the instance, and bind the reference to b A* new_ref_container = new(&ref_container) A(b); std::cout << // &ref_container and new_ref_container are the same pointers "&ref_container = " << &ref_container << std::endl << "new_ref_container = " << new_ref_container << std::endl << "&new_ref_container.ref = " << &new_ref_container->ref << std::endl << "&b = " << &b << std::endl << std::endl; return 0; }
demo
Die Ausgabe ist:
&ref_container.ref = 0x7ffdcb5f8c44 &a = 0x7ffdcb5f8c44 &ref_container = 0x7ffdcb5f8c38 new_ref_container = 0x7ffdcb5f8c38 &new_ref_container.ref = 0x7ffdcb5f8c40 &b = 0x7ffdcb5f8c40
quelle
std::launder
.Obwohl es eine schlechte Idee ist, da es den Zweck der Verwendung von Referenzen zunichte macht, ist es möglich, die Referenz direkt zu ändern
const_cast< int& >(ref)=b;
quelle