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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7713266/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 17:22:56  来源:igfitidea点击:

How can I change the variable to which a C++ reference refers?

c++referencedynamic-rebinding

提问by Taru

If I have this:

如果我有这个:

int a = 2;
int b = 4;
int &ref = a;

How can I make refrefer to bafter this code?

如何在此代码后ref引用b

回答by Bj?rn Pollex

This is not possible, and that's by design. References cannot be rebound.

这是不可能的,这是设计使然。引用不能被反弹。

回答by David C. Bishop

With C++11 there is the new(ish) std::reference_wrapper.

在 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);
}

This is also useful for storing references in containers.

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

回答by John Humphreys - w00te

You can't reassign a reference, but if you're looking for something that would provide similar abilities to this you can do a pointer instead.

你不能重新分配一个引用,但是如果你正在寻找可以提供类似能力的东西,你可以做一个指针。

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.

You can get or set the value within pointer with: 

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

*ptr = 5;     //set
int c = *ptr; //get

回答by Griwes

You cannot reassign a reference.

您不能重新分配参考。

回答by xuancong84

Formally speaking, that is impossible as it is forbidden by design. Arbitrarily speaking, that is possible.

正式地说,这是不可能的,因为这是设计禁止的。随意地说,这是可能的。

A references is stored as a pointer, so you can always change where it points to as long as you know how to get its address. Similarly, you can also change the value of const variables, const member variables or even private member variables when you don't have access to.

引用存储为指针,因此只要知道如何获取其地址,就可以随时更改它指向的位置。同理,当你无权访问时,你也可以改变const变量、const成员变量甚至私有成员变量的值。

For example, the following code has changed class A's const private member reference:

例如,以下代码更改了类 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;
}

Program output:

程序输出:

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

As you can see that a.i1initially points to i, after the change, it points to j.

如您所见,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.

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

回答by Mark B

That's not possible in the way you want. C++ just doesn't let you rebind what a reference points to.

这是不可能的。C++ 只是不允许您重新绑定引用指向的内容。

However if you want to use trickery you can almost simulate it with a new scope (NEVERdo this in a real program):

但是,如果你想使用技巧,你几乎可以用一个新的范围来模拟它(永远不要在真实的程序中这样做):

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.
}

回答by Taster

You can make a reference wrapper very easy using the placement new:

您可以使用放置 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

回答by Zhaolin Feng

This is possible. Because under the hood, reference is a pointer. The following code will print "hello world"

这个有可能。因为在引擎盖下,引用是一个指针。以下代码将打印“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());
}

回答by visu

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;