iPhone
 Computer >> コンピューター >  >> スマートフォン >> iPhone

1 人の母親と 2 人の息子の物語:Swift の値型と参照型

Swift は母親ですか?そして 2 人の息子がいますか?-

  • 値のタイプ ??‍♀️
  • 参照タイプ ?‍♂️

しかし、彼らの特徴は何ですか??‍♂️

それらは互いに同じように振る舞いますか、それとも反対に振る舞いますか? ?‍♂️

Swift は、Apple が iOS、macOS、watchOS、tvOS、Linux、および z/OS 用に開発したマルチパラダイム プログラミング言語です。

他のオブジェクト指向プログラミング言語と同様に、Swift には、メソッド、プロパティ、初期化子を定義でき、プロトコルに準拠し、継承とポリモーフィズムをサポートできるビルディング ブロックとしてのクラスがあります。

でも、ちょっと待って…???

Swift には構造体もあり、メソッド、プロパティ、イニシャライザを定義でき、継承を 1 つだけ例外としてプロトコルに準拠できます。

何?今、私は混乱しています!!! ???

Swift では、構造体は単なる値型ではありません。タプルと列挙型も値型です。参照型として使用されるのはクラスだけではありません。関数とクロージャも参照型です。しかし、安心のしるしとして、少なくともこれらのタイプの使用の主な焦点と専門化を知っています.?

ここまでで、構造体とクラスの使用法に関する大きな混乱が 1 つだけ残っています。

それでは、周りの混乱を解消しましょう.?‍♂️

保管場所

利用可能なストレージには 3 つのタイプがあります:

  • 登録しますか?
  • スタック ☄️
  • ヒープ?

寿命が短いオブジェクトはレジスタまたはスタック内に格納され、寿命が長いオブジェクトはヒープ内に格納されます。

値型はその内容をスタックに割り当てられたメモリに格納するため、値型は Swift のスタックに割り当てられていると言えます。 ?

しかし、値の型についてよくある誤解があります。聞いたことがありますか??‍♂️

ほとんどの人は、値の型は常にスタックに格納されると考えているというのは誤解です。

❌❌ ちょっと待ってください — これは常に当てはまるわけではありません。 ❌❌

値の型は、一時変数またはローカル変数のいずれかである場合、スタック内に格納できます。しかし、値型が参照型に含まれている場合はどうなるでしょうか?

この場合、ヒープメモリ内に格納できます。 ?

うわー…かっこいい!!!?

したがって、値型は、寿命が短いか長いかにかかわらず、寿命に応じてレジスタ、スタック、またはヒープ内に格納できます。ローカル変数の場合はスタック内に存在でき、クラスの一部である場合はヒープ メモリ内にも存在できます。✅

一方、参照型はその内容をヒープメモリに割り当てられたメモリに格納し、変数は実際のデータが格納されているメモリ位置への参照のみを保持します。 ??

参照型ではどのように機能しますか??

したがって、参照型の場合、複数の変数が同じメモリ位置への参照を保持している可能性があるというのは、非常に一般的な状況です。⚔️

値型インスタンスが変数に割り当てられるか関数に渡されると、インスタンスがコピーされてその変数に割り当てられます。しかし、参照型では、参照のみがコピーされ、新しい変数は同じメモリ位置への同じ参照を保持します。 ?

可変性の違い

変数には 2 つの状態があります:

  • ?‍♀️可変?‍♀
  • ?️‍♂️ 不変 ?️‍♂️

値型のインスタンスが不変変数に割り当てられている場合、そのインスタンスも不変になります。その結果、そのインスタンスに変更を加えることはできません.?‍♂️

値型のインスタンスが変更可能な変数に割り当てられている場合、そのインスタンスのみが変更可能になります。 ?‍♂️

しかし、参照型の場合はまったく異なります。変数とそれが代入されるインスタンスはまったく異なります。クラスへの参照を保持する不変変数を宣言すると、保持している参照が変更されないことを意味します。参照を変更することはできず、常に同じ参照を指します。 ?

構造型

構造型の値は、属性または要素に関して等しいかどうか比較されます。対応するすべての属性が等しい場合にのみ、値の型が別の型と等しいと言えます。 ???

うーん…強い言葉が多すぎます…どういう意味ですか???

たとえば、Person がいるとしましょう firstName のような属性を持つ値型 そして名字

struct Person {
   var firstName: String
   var lastName: String
}

var person1 = Person(firstName: "foo", lastName: "bar")

var person2 = Person(firstName: "foo", lastName: "bar")

ここでは両方の person1 &person2 インスタンスは firstName に対して同じ値を保持しています (「フー」) および 姓 (「バー」) . したがって、私たちの理解では、2 つのインスタンスは属性 (firstName) であるため、互いに等しいと言えます。 &名字 ) は同じ値を保持しています。

しかし、これだけに限定されているわけではありません:将来、firstName に対して同じ値を保持する 2 つの person インスタンス &名字 互いに等しくなります。

したがって、この時点までの理解によれば、次のように言えます。

値型には ID がないため、値型への参照はありません。値型には顔がない?

何?どうしてそんなことが言えるの????

var myAge: Int = 21
var friendAge: Int = 21

両方 myAge &friendAge 値が 21 の整数型変数です。

お互いを区別できますか? ?

いいえ、同じ値を保持しているためです。

値 21 を持つ整数変数は、値 21 を持つ別の整数変数と異なることはできません。それと同じくらい簡単です.???

ID を持たないことは、値型に別の利点をもたらします。実際に考えると、ID を持っていない場合、同じ特性を持つ誰かがあなたを置き換えたり代用したりできることを想像できます。 ???

私たち人間も同じように考えることができます。私がアイデンティティを持っていない場合、同じ特性を持つ誰かが私を置き換えることができます???.私たちがアイデンティティを持っていることは私たちにとって良いことです。

しかし、値型の場合、ID がなく、それが利点になります。 ?

値型を使用する利点は何ですか?

?競合状態とデッドロックなし:?

マルチスレッド環境の値型の場合、あるスレッドが別のスレッドによって使用されている間にインスタンスの状態を変更することはできません。したがって、競合状態やデッドロックは発生しないと言えます。

⚔️ 保持サイクルなし:⚔️

2 つの参照型インスタンスが互いに強い参照を保持し、メモリからの割り当て解除を妨げている場合、これは保持サイクルと呼ばれます。値型は参照として機能しないため、値型の保持サイクルはないと言えます。

?‍?‍?‍?自動参照カウント:?‍?‍?‍?

参照型の場合、Swift は自動参照カウントを使用してすべてのライブ オブジェクトまたはアクティブ オブジェクトを追跡し、インスタンスへの強い参照がなくなった場合にのみインスタンスの割り当てを解除します。少し考えてみると、Swift ランタイムは常にオブジェクトを追跡する必要があるため、これは一種の重い操作であると言えます。ただし、値型はスタックに割り当てられるため、ARC は必要ありません。では、安くて速いのでしょうか??.

でも待ってください...配列、辞書、文字列のメモリをどのように管理しますか?

配列、辞書、および文字列の実際のサイズはコンパイル時にわからないため、コンパイル時にそれらを割り当てるスコープはありません。内部的には値型ですが、スタックに配置することはできません。これらはヒープ メモリに割り当てる必要があり、これを管理するために、Swift は copy on write を考え出します。 .?

しかし、これは何ですか??

あるインスタンスが別のインスタンスのコピーであると言うとき、これは実際にはそれらが同じであること、つまり同じ値を含んでいることを意味します。しかし、Swift では、上記の型 (Array、Dictionary、String など) の場合、実際のコピーはインスタンスが変更された場合にのみヒープに作成されます。これは、値型のパフォーマンス最適化手法と呼ばれます。???

結論

いつ値型を使用し、いつ参照型を使用するかを定義する厳密な規則はありません。値型には、参照型よりも優れた利点があり、その逆もあります。どちらも独自の方法でユニークです。それは本当にあなたの要件とあなたが達成しようとしているものに依存します.自分のコードを最もよく知っているのは自分だけなので、自分のコードのセマンティクスを知っておく必要があります。選択するのは自分次第です。あなたには完全な自由があります。

したがって、値型と参照型を争うのではなく、それらを賢く使用してください。

???乾杯!!!読んでくれてありがとう!! ???

✅✅✅あなたは私を見つけることができます ツイッター .✅✅✅


  1. C#での値型と参照型の説明と対比

    一般に、C#のすべての型は、2つの主要なカテゴリ(値型)に分類できます。 および参照型 。それぞれのタイプを詳しく見ていきましょう。 値型 値型の変数には、データが直接含まれています。各変数には、データの独自のコピーがあります。したがって、値型の変数が別のオブジェクトを変更することはできません。 値の型は、次のいずれかの型になります- すべての数値型( int、float、など) およびダブル char およびブール タイプ 構造体 タイプまたは 列挙 タイプ。 simpleの値型には、値が含まれます。たとえば、整数型には実際の数値が含まれ、参照型のように数値へのポインタは含

  2. Generics と Swift の Any 型の違いを分析しましょう

    Swift は、現在最もタイプセーフな言語の 1 つです。 ??? ああ、待って!!言語が型安全であるとはどういう意味ですか? ? 型安全な言語により、その時点で利用可能な適切な種類のデータで操作が機能することが常に保証されます。✓ 言語にさまざまなデータ型 (例:Int、Float、String、Array、Dictionary) を宣言する機能があり、特定のデータ型で宣言された変数が異なる種類の変数を決して保持しないようにする機能もある場合。 型安全な言語では、型チェックは常に行われます。言語によっては、コンパイル時または実行時に発生する可能性があります.✅ さて、Swift