如何更改C++引用所引用的变量?

Tar*_*aru 63 c++ reference dynamic-rebinding

如果我有这个:

int a = 2;
int b = 4;
int &ref = a;
Run Code Online (Sandbox Code Playgroud)

如何在此代码后ref引用b

Bjö*_*lex 82

这是不可能的,这是设计的.参考不能反弹.

  • 您没有更改引用,您将`k`的值赋给由`x`引用的对象.在这个赋值之后,`a == k`和`x`仍然是指`a`. (4认同)
  • 在下面的代码中,我将 x 的引用更改为 k 并且仍然得到结果。你能告诉我这怎么可能吗?整数a=50;int &x=a; 整数k=10;cout<<x<<endl; x=k;cout<<x<<endl; (2认同)

Dav*_*hop 71

使用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);
}
Run Code Online (Sandbox Code Playgroud)

这对于在容器中存储引用也很有用.


Joh*_*0te 19

你不能重新分配一个引用,但是如果你正在寻找能够提供相似功能的东西,你可以改为使用指针.

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.
Run Code Online (Sandbox Code Playgroud)

您可以使用以下命令获取或设置指针中的值: 

*ptr = 5;     //set
int c = *ptr; //get
Run Code Online (Sandbox Code Playgroud)

  • 你正在重新声明`ptr`. (4认同)

Gri*_*wes 8

您无法重新分配参考.


Mar*_*k B 7

这不可能以你想要的方式.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.
}
Run Code Online (Sandbox Code Playgroud)

  • 几乎-1值得 (13认同)

xua*_*g84 7

从形式上讲,这是不可能的,因为它被设计禁止.任意地说,这是可能的.

引用存储为指针,因此只要您知道如何获取其地址,就可以始终更改它指向的位置.同样,当您无权访问时,您还可以更改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;
}
Run Code Online (Sandbox Code Playgroud)

节目输出:

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
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,a.i1最初指向i,在更改之后,它指向j.

但是,这样做被认为是危险的,因此不推荐,因为它违背了数据封装和OOP的最初目的.它更像是内存地址黑客攻击.

  • 这是不正确的:引用根本不需要是指针/对象。根据标准,它只需表现得像同一对象的不同标签。尝试改变这是未定义的行为。如果您的特定程序中的编译器决定通过指针实现它,您也许可以更改它,但这也可能随时中断。 (3认同)
  • 这就是为什么我在第一句话中提到:“从形式上讲,这是不可能的,因为这是设计所禁止的。” 我只是提供了一个实现级别的解决方法。 (2认同)