struct — その概要、主要な概念、Swiftでの構文

著者: IT Sectr 公開日: 2026-06-17 読了時間: 7 分

StructはSwift言語における値型(value type)であり、そのインスタンスはコードの各部分間で渡される際にコピーされます。クラスとは異なり、構造体は継承をサポートしませんが、プロトコルを実装し、プロパティとメソッドを持ち、ARCなしで予測可能なメモリ管理を提供します。Swift Programming Language Guide, 2026によると、structはSwiftの基本的な構成要素であり、Int、String、Array、Dictionaryといった標準型でさえ構造体として実装されています。言語はデータモデリングの優先選択として構造体を推奨しています。

重要なポイント

  • StructはSwiftの値型で、代入時にコピーされ、参照ではなく値で渡されます。
  • Copy-on-Writeは、実際のデータコピーが代入時ではなく値の変更時にのみ発生する最適化です。
  • Mutatingは、構造体のプロパティを変更するメソッドに必要なキーワードです。
  • プロトコル — 構造体はプロトコルと拡張を実装でき、継承なしで柔軟性を提供します。
  • 安全性 — 参照サイクルがないため、マルチスレッドコードやデータモデルに構造体が適しています。

Swiftのstructとは?

Struct(構造体)は、関連するプロパティとメソッドを単一のエンティティにグループ化するSwiftの複合データ型です。クラスとは異なり、構造体は値型です。関数に渡したり新しい変数に代入したりすると、元のオブジェクトへの参照ではなく、構造体の独立したコピーが作成されます。

Swiftはすべてのプリミティブ型に構造体を使用します:Int、Double、String、Bool、Array、Dictionary、Set。つまり、基本的なIntでさえ構造体のように振る舞い、代入時にコピーが作成されます。開発者は任意のプロパティとメソッドのセットで独自の構造体を定義できます。

Swift Evolution(SE-0143)によると、標準型を構造体として実装する決定は、パフォーマンスと予測可能性に基づいています。値型は参照サイクルを作成せず、ARC参照カウントを必要とせず、コピーの変更がオリジナルに影響しないことを保証します。これはマルチスレッドシナリオでのデータの不変性にとって極めて重要です。

値型としてのstruct

値型のセマンティクスがstructとclassの主な違いです。構造体を新しい変数に代入したり関数に渡したりすると、Swiftはすべてのデータの独立したコピーを作成します。コピーへの変更はオリジナルに影響を与えず、参照型に特有の副作用を排除します。

swift
// 値型セマンティクスの例
struct Point {
    var x: Double
    var y: Double
}

var p1 = Point(x: 10, y: 20)
var p2 = p1        // p2はp1の独立したコピー
p2.x = 99            // p2のみ変更
print(p1.x)         // 10 — p1は変更なし
print(p2.x)         // 99

Copy-on-Write最適化

Swiftはコピーの最適化にCopy-on-Write(COW)を使用します。複数の変数が同じ構造体を参照していても、どれもデータを変更しない場合、実際のコピーは発生しません。Swiftは最初の変更まで変数間でメモリを共有し、その時点で実際のコピーが作成されます。これにより過剰な割り当て操作を防ぎ、コレクションの操作を高速化します。

可変性とmutatingメソッド

デフォルトでは、構造体のメソッドはそのプロパティを変更できません。Swiftは変更を行うメソッドに明示的なmutatingキーワードを要求します。この制限は偶発的な変更を防ぎ、コードを予測可能にします。メソッドがmutatingとマークされていない場合、構造体を変更しないことが保証されます。

Mutatingの動作

メソッドの前にmutatingキーワードを追加すると、Swiftは構造体のプロパティに新しい値を書き込む能力を得ます。実際、メソッドはself = を介して構造体インスタンスを完全に新しいものに置き換えることさえできます。このメカニズムは、例えばOption型やResult型で使用されています。

swift
// mutatingメソッドを持つstruct
struct Counter {
    private var value: Int = 0

    // Mutatingメソッド — プロパティを変更可能
    mutating func increment() {
        value += 1
    }

    // Mutatingメソッドはselfを完全に置き換え可能
    mutating func reset() {
        self = Counter()
    }

    // 非mutatingメソッド — 読み取り専用
    func currentValue() -> Int {
        return value
    }
}

var counter = Counter()
counter.increment()
print(counter.currentValue())  // 1
counter.reset()
print(counter.currentValue())  // 0

Mutatingのルール:構造体はvarで宣言する必要があり、letでは宣言できません。定数構造体はmutatingメソッドを呼び出せません。コンパイラはビルド時にこれをチェックし、let定数でmutatingメソッドを呼び出そうとするとコンパイルエラーになります。

Struct vs Class: 比較

structとclassの選択は、Swiftにおける基本的な判断の一つです。どちらの型もプロパティ、メソッド、イニシャライザを持ち、プロトコルを実装できますが、メモリセマンティクス、継承、ライフサイクル管理に根本的な違いがあります。

特性structclass
値型(コピーされる)参照型(参照)
継承サポートしないサポートする
ARC / 参照カウント不要ARC必要
デイニシャライゼーションサポートしないdeinitをサポート
定数でのプロパティ変更varのみ可能letでも可能(参照は定数)
型キャストサポートしないサポートする
コレクション内の格納直接格納(値)参照として格納(ポインタ)

構造体は、データが継承を必要としない場合、共有アイデンティティを持つべきでない場合(例:座標、サイズ、設定)、モジュール間で渡される場合に適しています。クラスはUIコンポーネント(UIView、UIViewController)、シングルトン、共有アイデンティティを持つオブジェクトに選ばれます。

structを選ぶべき時

AppleはSwiftでのデータモデリングにstructをデフォルト型として使用することを推奨しています。構造体は、予測可能なコピーセマンティクスと参照カウントのオーバーヘッドがないため、ほとんどのシナリオに適しています。structが最適な選択となる典型的なケースを見てみましょう。

継承のないデータモデル

エンティティが継承を必要とせずにデータを含む場合(Product、User、Order、Point)、structを使用します。コンパイラは自動的にメンバーワイズイニシャライザを生成するため、手動でinitを書く必要はありません。EquatableとHashableも、すべてのプロパティがこれらのプロトコルに準拠する構造体に対して自動的に実装されます。

不変データ

作成後に変更されない設定やフラグには、classよりもstructが適しています。定数(let)構造体はすべてのネストされたフィールドの不変性を保証しますが、classではこれは参照にのみ適用され、オブジェクトの内容には適用されません。

マルチスレッドコード

値セマンティクスにより、構造体はマルチスレッド環境で安全です。各スレッドはデータの独立したコピーを取得し、他のスレッドに影響を与えません。値型ではスレッド間のデータ競合が不可能であり、SwiftUIのモデルではstructが推奨されます(ObservableObjectはclassが必要ですが、@Stateはstructを使用します)。

swift
// データモデルでのstruct使用例
struct User: Codable, Identifiable {
    let id: UUID
    var name: String
    var email: String
    var isPremium: Bool

    // 算出プロパティ — 非mutating
    var displayName: String {
        isPremium ? "\(name) ⭐️" : name
    }
}

// 自動メンバーワイズイニシャライザ
let user = User(
    id: UUID(),
    name: "Alice",
    email: "alice@example.com",
    isPremium: true
)

// マルチスレッドでも安全なコピー
var userCopy = user
userCopy.isPremium = false
// user.isPremiumはtrueのまま

継承(UIKit/AppKitコンポーネント)、共有アイデンティティ(delegate、observer)、または制御されたオブジェクトライフサイクル(deinit)が必要な場合はclassを使用してください。それ以外のすべてにはstructを使用してください。

よくある質問

Swiftのstructとは?

StructはSwiftの値型で、コードの各部分間で渡される際にコピーされます。構造体はプロパティ、メソッド、イニシャライザを持ち、プロトコルを実装できます。Swiftの基本型(Int、String、Array)は構造体として実装されています。

Swiftのstructとclassの違いは?

Structは値型(代入時にコピー)、継承をサポートせず、ARC不要。Classは参照型(参照で渡される)、継承、デイニシャライゼーション、参照カウントをサポート。開発者はstructをデフォルト型として推奨しています。

Swift structのmutatingとは?

Mutatingは、構造体のメソッドがそのプロパティを変更できることを示すキーワードです。mutatingなしでは、コンパイラはフィールドの変更を禁止します。mutatingメソッドはvarで宣言された変数でのみ呼び出せ、letでは呼び出せません。

SwiftのCopy-on-Writeとは?

Copy-on-Write(COW)は、構造体に対するSwiftの最適化で、実際のデータコピーを最初の変更まで遅延させます。すべての変数が構造体を読み取るだけの間は、単一のメモリ領域を共有します。これにより大きなコレクションを扱う際のパフォーマンスが向上します。

Swiftでstructとclassはそれぞれいつ使うべき?

継承のないデータモデル、設定、DTO、マルチスレッドシナリオにはstructを使用。UIKit/AppKit UIコンポーネント、シングルトン、共有アイデンティティを持つエンティティ(delegate、observer)、デイニシャライゼーションが必要なオブジェクトにはclassを使用。

まとめ

  • StructはSwiftの値型で、代入時にコピーされ、コピー間で副作用のない予測可能な動作を提供します。
  • Copy-on-Writeは構造体のパフォーマンスを最適化し、実際のコピーは最初の変更時のみ発生し、毎回の代入時ではありません。
  • Swiftの標準型 — Int、String、Array、Dictionary — は構造体として実装され、すべての基本操作で値セマンティクスを保証します。
  • Mutatingは構造体のプロパティを変更するメソッドに必須のキーワードで、varインスタンスでのみ呼び出せます。
  • 構造体は継承をサポートしませんが、プロトコルを実装し、拡張を使用して機能を追加できます。
  • EquatableとHashableは、すべてのプロパティがこれらのプロトコルに準拠する構造体に対して自動的に実装され、比較やコレクションでの使用が容易になります。
  • Appleはstructをデフォルト型として推奨 — classは継承、共有アイデンティティ、または制御されたオブジェクトライフサイクルが必要な場合にのみ使用します。

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください