C ++ 참조가 참조하는 변수를 어떻게 변경할 수 있습니까?
이 경우 :
int a = 2;
int b = 4;
int &ref = a;
이 코드 다음에 어떻게 ref
참조 할 수 b
있습니까?
이것은 불가능 하며 의도적으로 설계된 것 입니다. 참조는 리바운드 될 수 없습니다.
C ++ 11에는 new (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);
}
이것은 컨테이너에 참조를 저장하는데도 유용합니다.
참조를 재 할당 할 수는 없지만 이와 유사한 기능을 제공하는 것을 찾고 있다면 대신 포인터를 사용할 수 있습니다.
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
참조를 재 지정할 수 없습니다.
그것은 당신이 원하는 방식으로 불가능합니다. C ++는 참조가 가리키는 것을 리 바인딩 할 수 없습니다.
그러나 속임수를 사용하려면 새 범위로 거의 시뮬레이션 할 수 있습니다 ( 실제 프로그램에서는 절대로 수행하지 마십시오 ).
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.
}
공식적으로 말하면 그것은 의도적으로 금지되어 있기 때문에 불가능합니다. 임의로 말하면 가능합니다.
참조는 포인터로 저장되므로 주소를 얻는 방법을 알고있는 한 항상 가리키는 위치를 변경할 수 있습니다. 마찬가지로 액세스 권한이 없을 때 const 변수, const 멤버 변수 또는 개인 멤버 변수의 값을 변경할 수도 있습니다.
예를 들어 다음 코드는 클래스 A의 const 전용 멤버 참조를 변경했습니다.
#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
a.i1이 처음에 i를 가리키고 있음을 알 수 있듯이 변경 후 j를 가리 킵니다 .
However, doing so is considered as dangerous and thus unrecommended, because it defeats the original purpose of data encapsulation and OOP. It is more like memory address hacking.
You can make a reference wrapper very easy using the placement new:
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
This is possible. Because under the hood, reference is a pointer. The following code will print "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());
}
Although its a bad idea as it defeats the purpose of using references, it is possible to change the reference directly
const_cast< int& >(ref)=b;
'Program Tip' 카테고리의 다른 글
선택한 Jquery 플러그인-선택한 값 가져 오기 (0) | 2020.11.22 |
---|---|
Swift에서 전체 화면 스크린 샷을 찍으려면 어떻게하나요? (0) | 2020.11.22 |
Groovy 내장 REST / HTTP 클라이언트? (0) | 2020.11.22 |
ASP.NET에서 현재 도메인 이름을 얻는 방법 (0) | 2020.11.22 |
Python에서 빈 개체 만들기 (0) | 2020.11.22 |