Jeśli mam to:Jak mogę zmienić zmienną, do której odwołuje się C++?
int a = 2;
int b = 4;
int &ref = a;
Jak mogę dokonać ref
patrz b
po tym kodzie?
Jeśli mam to:Jak mogę zmienić zmienną, do której odwołuje się C++?
int a = 2;
int b = 4;
int &ref = a;
Jak mogę dokonać ref
patrz b
po tym kodzie?
To nie jest możliwe, a to by design. Odniesienia nie mogą być odbiciem.
Nie można ponownie przypisać odniesienia.
Nie można ponownie przypisać odniesienia, ale jeśli szukasz czegoś, co zapewnia podobne możliwości, możesz zamiast tego użyć wskaźnika.
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.
można uzyskać lub ustawić wartość wskaźnika z wewnątrz:
*ptr = 5; //set
int c = *ptr; //get
Jesteś redeclaring 'ptr'. –
nie jest to możliwe w sposób chcesz. C++ po prostu nie pozwala ci powtórzyć tego, na co wskazuje punkt odniesienia.
Jednak jeśli chcesz używać sztuczek można prawie zasymulować z nowym zakresem (NIGDY to zrobić w prawdziwym programu):
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.
}
prawie -1 godny – ThomasMcLeod
z C++ 11 nie jest nowy (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);
}
Jest to również przydatne do przechowywania referencji w pojemnikach.
Chociaż jest to zły pomysł, gdyż celowość stosowania odniesień, jest możliwe, aby zmienić odniesienie bezpośrednio
const_cast< int& >(ref)=b;
To zabawne, jak ludzie dają +1 złe rozwiązanie. Ten kod zmieni zmienną, gdzie ref wskazuje, a nie samą referencję. – Slava
Nic już mnie nie zaskakuje na stronach Exchange: D – GameDeveloper
Hej, to jest oczywiście zła odpowiedź. @visu, usuń go. – einpoklum
można dokonać wrapper odniesienie bardzo łatwe przy użyciu umieszczenie nowego:
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
Ta odpowiedź jest o wiele bardziej skomplikowana, niż jest to konieczne - pytanie było bardzo proste i można było odpowiedzieć jednym linerem. – lukelazarovic
Jest to możliwe. Ponieważ pod maską odniesienie jest wskaźnikiem. Poniższy kod wypisze „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());
}
Niezależnie od tego, jaki masz wpływ na UB, nie oznacza to, że "działa". – Slava
@Slava: Czy to w rzeczywistości niezdefiniowane zachowanie? Czy odniesienie nie jest zdefiniowane jako "wskaźnik w przebraniu", że tak powiem? – einpoklum
'otherVariable' nie jest wymagany przy użyciu' * ((uintptr_t * this this) = ((uintptr_t) & str) 'in' setRef' – joas
Formalnie rzecz biorąc, jest to niemożliwe, ponieważ jest to zabronione przez projekt. Mówiąc arbitralnie, jest to możliwe.
Odwołania są zapisywane jako wskaźniki, więc zawsze można zmienić ich położenie, o ile wiadomo, jak uzyskać jego adres. Podobnie możesz zmienić wartość zmiennych stałych, zmiennych składowych stałych, a nawet zmiennych prywatnych, gdy nie masz do nich dostępu.
Na przykład, następujący kod zmieniła Klasa A jest const prywatną odniesienie użytkownika: wyjście
#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;
}
Program:
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
Jak widać że a.i1 początkowo wskazuje na i, po zmianie wskazuje na j.
Jednak jest to uważane za niebezpieczne, a zatem niezalecane, ponieważ pokonuje pierwotny cel enkapsulacji danych i OOP. To bardziej przypomina hackowanie adresów pamięci.
W kodzie poniżej zmieniam odniesienie x do k i nadal otrzymuję wynik. Czy możesz mi powiedzieć, jak to jest możliwe? int a = 50; int &x=a; int k = 10; cout << x << endl; x = k; cout << x << endl; – Rajesh
Nie zmieniasz odniesienia, przypisujesz wartość 'k' do obiektu, do którego odnosi się' x'. Po tym przypisaniu, 'a == k' i' x' nadal odnosi się do 'a'. –