92

私がこれを持っている場合:

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

このコードの後に​​どのようにref参照させることができますか?b

4

10 に答える 10

112

これは不可能であり、これは仕様によるものです。参照をリバウンドすることはできません。

于 2011-10-10T13:15:44.840 に答える
92

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

これは、参照をコンテナに保存する場合にも役立ちます。

于 2013-11-27T04:01:29.997 に答える
22

参照を再割り当てすることはできませんが、これと同様の機能を提供するものを探している場合は、代わりにポインターを実行できます。

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
于 2011-10-10T13:26:57.640 に答える
10

参照を再割り当てすることはできません。

于 2011-10-10T13:16:29.053 に答える
10

正式に言えば、それは設計上禁止されているため不可能です。恣意的に言えば、それは可能です。

参照はポインタとして保存されるため、アドレスの取得方法を知っている限り、参照先をいつでも変更できます。同様に、にアクセスできない場合は、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;
}

プログラム出力:

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の本来の目的が損なわれるため、危険であると見なされ、推奨されません。これは、メモリアドレスのハッキングに似ています。

于 2015-09-16T10:57:17.020 に答える
6

それはあなたが望む方法では不可能です。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.
}
于 2011-10-10T13:43:26.070 に答える
3

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
于 2014-03-28T10:31:33.763 に答える
3

これは可能です。内部的には、参照はポインタであるためです。次のコードは「helloworld」を出力します

#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());
}
于 2015-05-21T14:04:31.993 に答える
0

他の答えが述べているように、それは不可能です。

classただし、参照をまたはに格納すると、struct配置newを使用して全体を再作成できるため、参照が再バインドされます。std::launder@HolyBlackCatが指摘したように、再作成されたオブジェクトにアクセスするために使用するか、新しい配置から返されたポインターを使用することを忘れないでください。私の例を考えてみましょう:

#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

出力は次のとおりです。

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

&ref_container = 0x7ffdcb5f8c38
new_ref_container = 0x7ffdcb5f8c38
&new_ref_container.ref = 0x7ffdcb5f8c40
&b = 0x7ffdcb5f8c40
于 2020-11-12T12:12:50.597 に答える
-5

参照を使用する目的が損なわれるため、これは悪い考えですが、参照を直接変更することは可能です。

const_cast< int& >(ref)=b;
于 2014-03-19T19:32:44.200 に答える