はじめに
構造体とクラスの大きい違いは、構造体は値型、クラスは参照型ということです
この記事の目的は値型と参照型の違いをしることで、副次的に構造体とクラスの違いや使いわけるための知識を得ることを目指してます
今回の目的は値型と参照型の動作を見て構造体とクラスのイメージをつかむことなので細かいところは省いています
値型(構造体)と参照型(クラス)
C#でのデータ型の分類方法に値型と参照型というものがあります。
代表的なものを挙げてみると 値型は byte , short , int , long . 参照型は string , object , class などがあります
値型と参照型の違い
値型と参照型の違いはデータを格納する方法が違います
値型の変数は、値そのものが格納されます、それに対して参照型の変数はその値の参照(格納場所のアドレス)が格納されます
スタックとヒープ
また値型の実際の値 、参照型の参照(格納場所のアドレス)の値を格納するメモリ領域をスタック 、参照型の実際の値が格納されているメモリ領域のことをヒープといいます
スタック領域
スタック(LIFO)は最後に入れたものから順番に出していく(Last In Fast Out)の特徴を持った 一時的にデータを保管しておくメモリ領域のことです
またスタック領域は OSやコンパイラが領域を割り当て、解放を自動でしてくれます
ヒープ領域
ヒープ領域も一時的にデータを保管しておくメモリ領域ですが順番とかは関係なく動的に割り当て、解放ができます
言語によってはメモリの解放を手動でしますが 、C# はガベージコレクション(メモリの管理をしてくれるシステム)が自動でしてくれます
値型
参照型
値型と参照型の動作の違い
スタック領域の割り当て、解放のほうが軽量?
ガベージコレクションは動的に領域を割り当てと解放をするので管理が複雑、不要なメモリを解放する以外の動作(オーバーヘッド)がともなうのでスタック領域の割り当て、解放のほうが一般的に軽量。
注意点
前述したように値型と参照はデータの持ち方が違うので動作にも影響が出てきます
等価演算子( == )の場合
等価演算子は比較してる値もしくは、参照が同一かを比べています
なので参照型に等価演算子を用いると実際のデータ的には同じでも参照が違う可能性があるのでfalseが返ってくる場合があります
値型のイメージ
参照型のイメージ
参照が同じときの注意点
参照型のイメージ
参照が同じだと変更したときに参照が同じオブジェクトのデータがすべて変わってしまいます
例えば上の図の hogeにhoge.Append("ほげ"); をするとhogeとtestの参照が同一のためhogeだけではなくtestまで変更が加わってしまいます
値型は影響ないです
値型と参照型の使い分け
参照型はメモリを割り当てるときに参照をコピーし、値型の割り当てでは値全体をコピーするので大きいオブジェクトになると値型よりも参照型のほうがコストが低いです
参考
・https://uquest.tktk.co.jp/embedded/learning/lecture16.html
・https://learn.microsoft.com/ja-jp/dotnet/standard/design-guidelines/choosing-between-class-and-struct
。https://learn.microsoft.com/ja-jp/dotnet/csharp/programming-guide/statements-expressions-operators/equality-comparisons
・独習C# 第5版
まとめ
・構造体とクラスの大きな違いは値型と参照型であること
・値型と参照型の大きな違いはスタック領域かヒープ領域のどっちに実体を持つのかということ。またその違いで動作に影響が出てくること
・スタック領域とヒープ領域の違いはメモリの管理を自動的にするか 、ガベージコレクション(手動も可)でするかということ
・大きいオブジェクトだと参照型のほうが低コスト
以上です、お読みいただきありがとうございました。