2016-06-21 7 views
0

C++では、正しく覚えていれば、関数へのパラメータは、参照として渡すことを示す&が指定されていない限り、値渡しされます。例えば C#での参照渡しがC++と比較してどのように動作するかについては正しいですか?

は、

int double (int i) 
{ 
    int twice = i * i; 
    return twice; 
} 

int main () 
{ 
    int i = 4; 
    int j = double(i); 
    return 0; 
} 

int i = 4; 
// --- here's the part where the function runs --- 
int temp = i; 
int twice = temp * temp; 
i = twice; 
// ----------------------------------------------- 

に相当し、intデータ型であるので、それはC#で同じように機能するであろう又は値型(私はき両方の用語が使われていると聞いた)。あなたがC#で参照型またはオブジェクトと呼ばれるものを渡すとき

物事が異なって取得することです。 C++では、&で修飾せずにclassを渡すと、この関数はパラメータのディープコピーを使用しているかのように機能します。

たとえば、次のC++では、CharlieAgeがインクリメントされません。

class Dude 
{ 
    pulic Dude (name = "", age = 0) : Name(name), Age(age) { } 
    public string Name; 
    public int Age; 
} 

public void IncrementDudeAge (Dude dude) 
{ 
    ++dude.Age; 
} 

int main () 
{ 
    Dude Charlie = new Dude ("Charlie", 69); 
    IncrementDudeAge(Charlie); 
    std::cout << Charlie.Age; // prints 69 
} 

mainはC#で同じコードがAgeをインクリメントするであろうので、これは、C#とは異なる

Dude Charlie = new Dude ("Charlie", 69); 
    Dude temp = new Dude("Charlie", 69); 
    ++temp.Age; 
    std::cout << Charlie.Age; // prints 69 

と等価である:

public class Program 
{ 
    public static void IncrementDudeAge (Dude dude) 
    { 
     ++dude.Age; 
    } 

    public class Dude 
    { 
     public string Name { get; set; } 
     public int Age { get; set; } 
    } 

    public static void Main() 
    { 
     Dude Charlie = new Dude() { Name = "Charlie", Age = 69 }; 
     IncrementDudeAge(Charlie); 
     Console.WriteLine(Charlie.Age); // prints 70 
    } 
} 

コードのそのビットはCと等価である++コードのように

class Dude 
{ 
    pulic Dude (name = "", age = 0) : Name(name), Age(age) { } 
    public string Name; 
    public int Age; 
} 

public void IncrementDudeAge (Dude * dude) 
{ 
    ++*dude.Age; 
} 

int main () 
{ 
    Dude Charlie = new Dude ("Charlie", 69); 
    IncrementDudeAge(&Charlie); 
    std::cout << Charlie.Age; // prints 70 
}  

つまり、上記2つのコードではCharlieの別名を渡しています。Charlieを指しているもののコピーです。 C++では、エイリアスは実際の整数型ですが、C#ではエイリアスと考えることができます。

両方のケースでは、Charlieを指して何かのコピーですので、あなたが彼を再割り当てしようとした場合、あなたが実際Charlieには影響しません。

public void IncrementDudeAge (Dude * dude) 
{ 
    dude = new Dude ("Charlie", 70); 
} 

public static void IncrementDudeAge (Dude dude) 
    { 
     dude = new Dude() { Name = "Charlie", Age = 70 }; 
    } 

何もしないだろう。 C#でref、またはC++で**または*&を使用する必要があります。

私はすべてについて正しいですか?

+0

を:C#では、すべてのパラメータは、あなたが 'ref'または' out'キーワードを使用しない限り、値によって渡されていますが、C# 'class'オブジェクトを渡す時にしていますオブジェクトへの参照は値渡しされます。 C# 'struct'オブジェクト、または他の値型(組み込みの整数や浮動小数点型など)を渡すと、オブジェクト全体がスタックにプッシュされます。 –

答えて

3

tl; dr:はい。

私はC++に精通していませんが、AFAICS、あなたの説明は正しいようです。C♯で

、考慮すべき二つの独立した軸があります

  • パス・バイ・値対参照渡し参照型

注対

  • 値型を「参照」という言葉が2つの異なる意味で2回使用されていること。私たちは言葉を削除したい場合は、以下のように、我々は約それを書き換えることができます:

    • を値渡し対パスバイ結合
    • 値の型対ポインタ種類

    C♯では、値渡しがデフォルトです。特別なことをしないと、引数の受け渡しは例外なしで常にの値渡しです。 refキーワードの定義と呼び出しサイトの両方を明示的に指定すると、参照渡しをリクエストできます。 (参照渡し呼び出し先が間接参照に許可されていないとに必要とされる出力パラメータを対象とし、すべての可能なリターンパスで参照を初期化する特別な種類のあるoutキーワードもあります。)

    したがって、値渡しと参照渡しの違いは、で、引数が渡される方法はです。

    値型と参照型の差が渡されるものである:値のタイプと、値自体からポインタが渡される、参照型で渡されています。参照型は常にがポインタで動作し、値のタイプがの場合は常にであるため、ポインタを参照または参照解除するための特別な構文はありません。そのすべてが暗黙的です。しかしそれはそこにあります。

    これは私たちに四つの可能な組み合わせを提供します:基本的に

    struct MutableCell 
    { 
        public string value; 
    } 
    
    class Program 
    { 
        static void ArgumentPassing(string[] foo, MutableCell bar, ref string baz, ref MutableCell qux) 
        { 
         foo[0] = "More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value."; 
         foo = new string[] { "C# is not pass-by-reference." }; 
    
         bar.value = "For value types, it is *not* call-by-sharing."; 
         bar = new MutableCell { value = "And also not pass-by-reference." }; 
    
         baz = "It also supports pass-by-reference if explicitly requested."; 
    
         qux = new MutableCell { value = "Pass-by-reference is supported for value types as well." }; 
        } 
    
        static void Main(string[] args) 
        { 
         var quux = new string[] { "Yes, of course, C# *is* pass-by-value!" }; 
    
         var corge = new MutableCell { value = "For value types it is pure pass-by-value." }; 
    
         var grault = "This string will vanish because of pass-by-reference."; 
    
         var garply = new MutableCell { value = "This string will vanish because of pass-by-reference." }; 
    
         ArgumentPassing(quux, corge, ref grault, ref garply); 
    
         Console.WriteLine(quux[0]); 
         // More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value. 
    
         Console.WriteLine(corge.value); 
         // For value types it is pure pass-by-value. 
    
         Console.WriteLine(grault); 
         // It also supports pass-by-reference if explicitly requested. 
    
         Console.WriteLine(garply.value); 
         // Pass-by-reference is supported for value types as well. 
        } 
    } 
    
  • 2

    はい、正しいです。小さな発言の問題が指摘されることもありますが、すべての観察は問題ありません。

    関連する問題