2

英語は私の母国語ではなく、まさに中国人です。私の考えを明確に表現できなかったら申し訳ありません。

C++でプログラミングをしていました。私はC#の参照を本当に理解していません.多くの人は参照がc ++のポインタに似ていると私に言います.以下のように

Person Foo = new Person(); // C#
Person *Foo = new Person(); // C++.

多くの場合、うまく機能します。また、多くの C# コーダーは、クラスのインスタンスは単に Foo.Foo has name. whiched は Foo.name.Foo has age と呼ばれ、Foo.age. この考えの方がコーディングに慣れやすいようですが、この考えはメモリモデルに準拠していません。

参照がc#.aオブジェクトにあるのか、それともポインタである可能性が高いのか教えてください?Thx.

4

6 に答える 6

0

質問する前にそれをグーグルで検索しましたか?インターネットには多くの優れたリソースがあり、優れた電子書籍もあります。

ただし、C# で使用されるメモリ モデルは次のとおりです (Java と PHP でもほぼ同様です)。

  1. すべてのオブジェクトはクラス オブジェクトから継承されます。つまり、ほとんどすべてが C# のオブジェクトです。
  2. もうポインターを使用する必要はありません。C# ではほとんど必要ありません。オブジェクトを作成すると、スタック内のインスタンスへの参照が返されます。スタック内の 1 つのオブジェクトへの参照を多数持つこともできます。参照はヒープにあります。これはデフォルトの動作であり、ネイティブ コードを実行しない限り変更できません。
  3. 何かを削除する必要はありません。これは、ガベージ コレクターによって自動的に行われます。メソッドの最後に作成されたすべてのローカル変数が削除されます。ガベージ コレクターは、参照されなくなったオブジェクトも削除します。
  4. 内部データ型は常にスタックに配置され、文字列も同様です。文字列については、ここで例外を作成しました。文字列もオブジェクトとしてではなく、単純なデータ型として扱われます。
  5. たとえば、メソッドに int 値を指定した場合、すべての内部データ型がデフォルトでコピーされます。このパターンは「Call-By-Value」と呼ばれます。すべてのオブジェクトは、新しい参照によって渡されます。つまり、メソッド パラメーターとしてオブジェクトを指定すると、メソッド内でオブジェクトへの新しい参照が取得されるだけです。このパターンは「Call-By-Reference」と呼ばれます。それらを分割することは非常に重要です。
  6. 「ref」キーワードを使用して、Call-By-Value を Call-By-Reference に変更できます。out パラメータのみを定義することもできます。つまり、メソッドにどのような値を与えるかは問題ではありません。メソッドの最後に何かを返すだけです。これは、C# で「out」キーワードを使用して実行できます。
  7. これに対する論理的な結論として、C# ではヒープをオーバーフローさせることはできません。スタックがオーバーフローする前に...
  8. 静的呼び出しとオブジェクト呼び出しの違いはもうありません。それは常にドットです。したがって、クラスの public static メンバーを呼び出すのと同じ方法で、クラスの public メンバーを呼び出すことができます。静的メンバーの場合、クラス名を使用するか、変数名の前にキーワードを付けずにクラス内で使用する必要があります。オブジェクト/クラス メンバーへの参照を使用して呼び出します。
  9. 1 つのクラスからしか継承できませんでした。多重継承は、C# (Java および PHP も同様) ではサポートされていません。
  10. 標準出力コマンド (>> および >) は、「コンソール」またはその他のストリーム参照 (ファイル出力ストリームなど) に変更されます。

編集:

子クラスは、基本クラスからすべてを継承し、プライベートおよび保護されたメンバー/メソッドも継承します。ただし、リフレクションを使用しない限り、パブリックおよび保護されたメンバー/メソッドにのみアクセスできます。

C# をもう少し理解するために、これが役立つことを願っています...

于 2014-04-27T17:47:50.777 に答える
0

C# にはガベージ コレクションがあり、既定ではポインターをサポートしていません。ただし、ここで概説されているようにポインターを使用できますhttp://msdn.microsoft.com/en-us/library/t2yzs44b(v=VS.80).aspx

于 2013-08-03T05:35:52.010 に答える
0

参照型と値型の違いに慣れたいと思うでしょう。

以下に例を示します。

void Main()
{
    Foo A = new Foo{Age = 16}; //A creates a space in memory for the data of Foo and points to that memory location
    Foo B = A; //B just creates a variable and points to the memory location created by A

    A.Bar();
    B.Bar();

    //Result
    //Your Age is 16
    //Your Age is 16

    A.Age = 24;

    A.Bar();
    B.Bar();

    //Result
    //Your Age is 24
    //Your Age is 24  <----- B is pointing to the same location as A and reflects the changes on call.

    FooValueType E = new FooValueType{Age = 23};
    FooValueType F = E;

    E.Bar();
    F.Bar();

    //Result
    //Your Age is 23
    //Your Age is 23

    E.Age = 56;

    E.Bar();
    F.Bar();

    //Result
    //Your Age is 56
    //Your Age is 23
}

public class Foo  //These object are by reference
{
    public int Age { get; set; }
    public void Bar()
    {
       Console.WriteLine("Your Age is {0}", Age);
    }
}

public struct FooValueType //These object are by value
{
    public int Age { get; set; }
    public void Bar()
    {
       Console.WriteLine("Your Age is {0}", Age);
    }
}
于 2013-08-03T05:37:10.453 に答える
0

あなたが言うときC#でPerson Foo = new Person();

  1. new Person()Personメモリを割り当ててクラスのオブジェクトを作成するheap section
  2. reference to memory allocatedPerson 型のこのオブジェクト (つまり のみ) への参照を返します。

Fooこの参照をキャッチしている間、この参照を使用して、オブジェクトのプロパティ、つまりそのmethods and variables.

C++ では、

reference to object同じ手順に従いますが、c++ ではa の apointerを typeでキャッチしますPerson


より具体的には、オブジェクトを作成するために割り当てをnew内部的に呼び出します。operator new functionmemory dynamically

以下に示すイメージでは、 Person p( on stack) は によって返されるオブジェクトへの参照を作成しますnew Person()

p.nameage と name は Object のメンバー変数であるため、 and を使用して簡単にアクセスできますp.age

ここに画像の説明を入力


C# と C++ の両方でのスタックとヒープのメモリ割り当てについてさらに追加する

  • 参照 Foo は常にスタック上のメモリを取得します
  • objectつまり、ここではnew Person()メモリをヒープに取得し、C#より具体的にはメモリを取得しますmanaged heap

アップデート

あなたが言うnew Person()と、タイプのオブジェクトに内部的にメモリを割り当てます - person.このオブジェクトはPersons members、画像に示すように構成されています。

その後、2つのことができます

  1. タイプの変数でこの参照をキャッチするか、Person たとえば、Person p = new Person(); ここpにオブジェクトのメモリ位置への参照があります。したがって、を使用してオブジェクトメンバーに簡単にアクセスできますp

  2. 参照を直接保存しないでください。たとえばnew Person().age、個人の年齢が表示されます。これは匿名オブジェクトと呼ばれます。

于 2013-08-03T05:38:23.880 に答える
0

変数の動作に関して、C# には 2 種類の型があります。

  • 値の型
  • 参照型

値型変数は、実際のオブジェクトを値として保持します。別の値型変数から割り当てられた値型変数を割り当てると、オブジェクト全体がコピーされます。C++ の用語で言えば、これは、たとえばスタックに割り当てられたインスタンスを作成する場合のように、(クラスへのポインターではなく) クラス型の変数を使用するようなものです。ただし、C# ではその選択肢はありませんが、この動作は構造体などの型にのみ制限されます。

参照型変数は、実際のオブジェクトへの参照を値として保持します。実際のオブジェクトへの参照には、少なくともオブジェクトのメモリ アドレスが含まれる可能性があります (ただし、詳細は隠されています)。別の参照型変数から参照型変数を割り当てると、 object ではなく参照がコピーされるため、2 つの変数が同じオブジェクトを指すようになります。C++ の用語で言えば、これはクラスのポインター変数を持つようなものです。ただし、C# は、クラスやインターフェイスなどの型の変数に対してデフォルトでこの動作を行います (私の知る限り、他の動作に戻る方法はありません)。C# 参照と C++ ポインターの主な違いは、C++ ポインターが算術演算をサポートしているのに対し、C# 参照はサポートしていないことです。これは、C# が私たちが呼び出すものを保証する方法の 1 つです。メモリ安全。(C# はポインターを提供しますが、それらはめったに使用されず、多くの場合、相互運用性のシナリオで役立ちます。C# でポインターを使用する必要が生じるまでには、長い時間がかかるでしょう。)

最終的には、C# リファレンスは C++ ポインターに近いと考えることができます (ただし、上記で概説したように、言語によって動作が異なり、制御と保護の程度が異なるため、違いがあります)。

于 2013-08-03T08:45:18.327 に答える
-2

参照は、オブジェクトへのポインタです。

C# では、アンセーフ コードで「実際の」ポインターを使用できます。例を次に示します。

于 2013-08-03T05:34:43.573 に答える