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

前端 未结 10 1000
既然无缘
既然无缘 2020-11-29 01:50

If I have this:

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

How can I make ref refer to b after this code?

相关标签:
10条回答
  • 2020-11-29 02:07

    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
    
    0 讨论(0)
  • 2020-11-29 02:08

    It is impossible, as other answers state.

    However, if you store your reference in a class or struct, you could re-create the whole thing using placement new, so the reference is re-bound. As @HolyBlackCat noted, don't forget to use std::launder to access the re-created object or use the pointer returned from the placement new. Consider my example:

    #include <iostream>
    
    struct A {
        A(int& ref) : ref(ref) {}
        // A reference stored as a field
        int& ref;    
    };
    
    int main() {
      int a = 42;
      int b = 43;
    
      // When instance is created, the reference is bound to a
      A ref_container(a);
      std::cout << 
        "&ref_container.ref = " << &ref_container.ref << std::endl <<
        "&a = " << &a << std::endl << std::endl;
    
      // Re-create the instance, and bind the reference to b
      A* new_ref_container = new(&ref_container) A(b);
      std::cout <<
        // &ref_container and new_ref_container are the same pointers
        "&ref_container = " << &ref_container << std::endl <<
        "new_ref_container = " << new_ref_container << std::endl <<
        "&new_ref_container.ref = " << &new_ref_container->ref << std::endl <<
        "&b = " << &b << std::endl << std::endl;
    
      return 0;
    }
    

    demo

    The output is:

    &ref_container.ref = 0x7ffdcb5f8c44
    &a = 0x7ffdcb5f8c44
    
    &ref_container = 0x7ffdcb5f8c38
    new_ref_container = 0x7ffdcb5f8c38
    &new_ref_container.ref = 0x7ffdcb5f8c40
    &b = 0x7ffdcb5f8c40
    
    0 讨论(0)
  • 2020-11-29 02:11

    With C++11 there is the 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.

    0 讨论(0)
  • 2020-11-29 02:17

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

    However if you want to use trickery you can almost simulate it with a new scope (NEVER do 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.
    }
    
    0 讨论(0)
  • 2020-11-29 02:22

    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());
    }
    
    0 讨论(0)
  • 2020-11-29 02:24

    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
    
    0 讨论(0)
提交回复
热议问题