我怎样才能改变一个C ++参考引用的variables?
如果我有这个:
int a = 2; int b = 4; int &ref = a;
这个代码后我怎么能参考b
?
这是不可能的,这是devise 。 参考资料不能被反弹。
在C ++ 11中有新的(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); }
这对于在容器中存储引用也很有用。
你不能重新分配一个引用,但是如果你正在寻找一些能够提供类似function的东西,你可以做一个指针。
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. }
从forms上讲,这是不可能的,因为它是被devise禁止的。 任意地说,这是可能的。
一个引用被存储为一个指针,所以只要你知道如何得到它的地址,你就可以随时改变它指向的地方。 同样,你也可以在没有权限的情况下改变constvariables,const成员variables甚至私有成员variables的值。
例如,下面的代码已经改变了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 。
然而,这样做被认为是危险的,因此不予推荐,因为它破坏了数据封装和OOP的原始目的。 这更像是内存地址黑客行为。
您可以使用新的放置位置来使参考包装非常简单:
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
这个有可能。 因为在引擎盖下,引用是一个指针。 以下代码将打印“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()); }
虽然它是一个坏主意,因为它违背了使用引用的目的,所以可以直接更改引用
const_cast< int& >(ref)=b;