2

以下のコードを見て、関数UpdateContextを呼び出した後、変数connection2が変数connection1と同じハッシュコードを持たない理由を教えてください。

変数connection2をconnection1に設定すると、両方の変数に同じメモリアドレスへのポインタがあります。ただし、「new」命令でポインターを変更する関数UpdateContextのrefによって変数connection1を渡した後、connection1には新しいポインターアドレスがありますが、connection2にはまだ古いアドレスがあります。

   class Program
   {
      static void Main(string[] args)
      {
         var connectionInitializer = new ConnectionInitializer();

         connectionInitializer.Initialize();

         Console.ReadLine();
      }
   }

   public class Connection
   {

   }

   public class ConnectionInitializer
   {
      public void Initialize()
      {
         var connection1 = new Connection();
         var connection2 = connection1;

         Console.WriteLine("Connection 1 (Before ref): " + connection1.GetHashCode());
         Console.WriteLine("Connection 2 (Before ref): " + connection2.GetHashCode());

         this.UpdateContext(ref connection1);

         Console.WriteLine("Connection 1 (After ref): " + connection1.GetHashCode());
         Console.WriteLine("Connection 2 (After ref): " + connection2.GetHashCode());
      }

      private void UpdateContext(ref Connection connection)
      {
         connection = new Connection();
      }
   }

ご協力ありがとうございました。

4

5 に答える 5

8

refあなたは何を達成しようとしているのか誤解しているようです。基本的に、変数をrefパラメーターとして渡すと、呼び出し先は(元の)変数の値をローカルであるかのように正確に変更できます。それを考えると、なぜ変数の値を上書きして、connection1割り当てられた値も変更することを期待するのでしょうconnection2か。

別の言い方をすれば、usingrefはこのコードに類似しています。

var connection1 = new Connection();
var connection2 = connection1;
connection1 = new Connection()

明らかに、このシナリオでconnection2は、変更しないでください。同じことがあなたにも当てはまります。

于 2012-06-07T00:03:53.793 に答える
3

connection2引き続き元のConnectionオブジェクトを参照します。 connection1新しいConnectionオブジェクトを参照するように変更されました。 connection1connection2文字通り同じ参照ではありません。 connection2はのコピーでconnection1あり、これらの参照の両方は、しばらくの間、同じオブジェクトを参照していました。

これらの2つの参照は、それらが参照しているものを除いて、意味のある方法でリンクされていません。一方は単にもう一方のコピーです。オリジナルを変更しても、コピーには反映されません。

于 2012-06-07T00:07:15.127 に答える
1

refKirk Woll の答えは正しいですが、キーワードを誤解しているという彼の発言は、少し的を射ていないと思います。この誤解は非常に一般的ですが、参照型自体の性質についての誤解です。

Kirk の説明 (「ref の使用はこのコードに類似しています」) は、実際には、「なぜ次の例が出力されないのGoodbyeですか?」など、私が思い出す他の SO の質問を反映しています。

string a = "Hello";
string b = a;
a = "Goodbye";
Console.WriteLine(b);

(申し訳ありませんが、実際の質問へのリンクが見つかりませんでした。)

参照型の変数は参照型のインスタンスへの参照を格納し、値型の変数は値型のインスタンスを直接格納することを覚えておくと、追跡がずっと簡単になります。

これは、通常の「参照型は参照によって渡され、値型は値によって渡される」よりもはるかに優れた考え方だと思います。実際、参照型の変数 (absentrefまたはout) は value で渡されますが、値自体は参照です。それは紛らわしいです。「参照型変数は、型のインスタンスへの参照を保持します」。

もちろん、refref パラメーターは変数への参照を保持するため、キーワードはこれを多少複雑にします。これは、参照型refパラメーターが型のインスタンスへの参照への参照を格納することを意味します。繰り返しになりますが、参照型の変数が参照を保持しているという事実を考えると、変数への参照を保持している ref パラメーターで停止できます。これは、「...への参照への参照」よりもはるかに簡単に推論できます。

于 2012-06-07T01:49:42.460 に答える
0

接続オブジェクトを初期化すると、新しいメモリが割り当てられるため、新しいハッシュコードが割り当てられます。

于 2012-06-07T00:04:49.927 に答える
0

C++ を話す場合、refs と outs は実際には単なるポインターであり、渡された識別子のアドレスを渡しています。比較:

void foo(int** p);

int main()
{
  int* one = new int(4);
  int* two = one;

  cout << "one|two before: " << *one << "|" << *two << endl;

  foo(&one);

  cout << "one|two after: " << *one << "|" << *two << endl;

  return 0;
}

void foo(int** p)
{
  *p = new int(5);
}

出力:

one|two before: 4|4
one|two after: 5|4

: C++ ref の受け渡しを使用することもできましたが、内部的には、それらも単なるポインターです。

于 2012-06-07T00:10:51.953 に答える