87 votes

Comment changer la variable à laquelle une référence C++ fait référence ?

Si j'ai ça :

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

Comment puis-je faire ref se référer à b après ce code ?

6voto

Mark B Points 60200

Ce n'est pas possible de la manière que vous voulez. Le C++ ne permet pas de lier à nouveau ce vers quoi pointe une référence.

Cependant, si vous voulez utiliser une astuce, vous pouvez presque la simuler avec une nouvelle portée ( JAMAIS faire cela dans un vrai programme) :

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

3voto

Taster Points 11

Vous pouvez créer un wrapper de référence très facilement en utilisant le nouveau placement :

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

3voto

Zhaolin Feng Points 153

C'est possible. Parce que sous le capot, la référence est un pointeur. Le code suivant imprimera " 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());
}

0voto

ivaigult Points 401

C'est impossible, comme l'indiquent d'autres réponses.

Cependant, si vous stockez votre référence dans un class o struct vous pourriez recréer l'ensemble en utilisant le nouveau placement, de sorte que la référence est liée à nouveau. Comme l'a noté @HolyBlackCat, n'oubliez pas d'utiliser std::launder pour accéder à l'objet recréé ou utiliser le pointeur renvoyé par le placement new. Prenons mon exemple :

#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

La sortie est :

&ref_container.ref = 0x7ffdcb5f8c44
&a = 0x7ffdcb5f8c44

&ref_container = 0x7ffdcb5f8c38
new_ref_container = 0x7ffdcb5f8c38
&new_ref_container.ref = 0x7ffdcb5f8c40
&b = 0x7ffdcb5f8c40

-5voto

visu Points 51

Bien que ce soit une mauvaise idée car cela va à l'encontre de l'objectif de l'utilisation des références, il est possible de changer la référence directement.

const_cast< int& >(ref)=b;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X