MENU

【Swift入門】inoutとは?使い方と実例を初心者向けに徹底解説

Swiftで関数を作成していると、「パラメータの値を変更したいのに、変更が反映されない」という壁にぶつかることがあります。その解決策の一つがinoutキーワードです。この記事では、Swiftのinoutについて、基礎から実践的な使い方まで初心者にもわかりやすく解説します。

目次

inoutとは何か

inoutは、Swiftで関数のパラメータを参照渡しにするためのキーワードです。

通常、Swiftの関数パラメータは値渡し(コピー)で渡されるため、関数内で値を変更しても呼び出し元には影響しません。しかし、inoutを使うことで、関数内での変更を呼び出し元に反映させることができます。

値渡しと参照渡しの違い

プログラミングには、データを関数に渡す方法として主に2つの方式があります。

値渡し(Pass by Value) データのコピーを関数に渡す方式です。関数内で値を変更しても、元のデータには影響しません。

参照渡し(Pass by Reference) データの参照(アドレス)を関数に渡す方式です。関数内で値を変更すると、元のデータも変更されます。

Swiftはデフォルトで値渡しですが、inoutを使うことで参照渡しを実現できます。

値渡しとinoutの違いを比較

まず、通常の値渡しの動作を見てみましょう。

値渡しの場合

func increment(number: Int) {
    var number = number  // パラメータをコピー
    number += 1
    print("関数内の値: \(number)")
}

var value = 5
increment(number: value)
print("関数外の値: \(value)")

// 出力:
// 関数内の値: 6
// 関数外の値: 5  ← 変更されていない

関数内で値を変更しても、呼び出し元のvalueは変更されません。

inoutを使った場合

func incrementWithInout(number: inout Int) {
    number += 1
    print("関数内の値: \(number)")
}

var value2 = 5
incrementWithInout(number: &value2)  // &をつける
print("関数外の値: \(value2)")

// 出力:
// 関数内の値: 6
// 関数外の値: 6  ← 変更されている!

inoutを使うと、関数内での変更が呼び出し元にも反映されます。

inoutの基本的な書き方

関数の定義

func 関数名(パラメータ名: inout 型) {
    // 処理
}

パラメータの型の前にinoutキーワードを記述します。

関数の呼び出し

関数名(パラメータ名: &変数名)

呼び出し時には、変数名の前に&(アンパサンド)をつけます。この&は「この変数の参照を渡しますよ」という意味を持ちます。

inoutの実践的な使用例

例1:2つの値を入れ替える

func swap(a: inout Int, b: inout Int) {
    let temp = a
    a = b
    b = temp
}

var x = 10
var y = 20
print("入れ替え前: x=\(x), y=\(y)")

swap(a: &x, b: &y)
print("入れ替え後: x=\(x), y=\(y)")

// 出力:
// 入れ替え前: x=10, y=20
// 入れ替え後: x=20, y=10

実は、Swiftの標準ライブラリにはswap()関数が用意されているため、実際にはこのように書けます。

var x = 10
var y = 20
swap(&x, &y)  // 標準ライブラリの関数

例2:配列の要素を直接変更

func doubleAllValues(array: inout [Int]) {
    for i in 0..<array.count {
        array[i] *= 2
    }
}

var numbers = [1, 2, 3, 4, 5]
print("変更前: \(numbers)")

doubleAllValues(array: &numbers)
print("変更後: \(numbers)")

// 出力:
// 変更前: [1, 2, 3, 4, 5]
// 変更後: [2, 4, 6, 8, 10]

例3:文字列を大文字に変換

func uppercaseString(text: inout String) {
    text = text.uppercased()
}

var message = "hello world"
print("変更前: \(message)")

uppercaseString(text: &message)
print("変更後: \(message)")

// 出力:
// 変更前: hello world
// 変更後: HELLO WORLD

例4:複数の値を同時に変更

func updateUserInfo(name: inout String, age: inout Int) {
    name = name.uppercased()
    age += 1
}

var userName = "taro"
var userAge = 25

updateUserInfo(name: &userName, age: &userAge)
print("名前: \(userName), 年齢: \(userAge)")

// 出力:
// 名前: TARO, 年齢: 26

inoutを使う際の注意点

1. 変数のみ渡せる

inoutパラメータには変数しか渡せません。定数や直接の値(リテラル)は渡せません。

func increment(number: inout Int) {
    number += 1
}

// これはOK
var mutableValue = 5
increment(number: &mutableValue)

// これはエラー
let constantValue = 5
// increment(number: &constantValue)  // エラー!

// これもエラー
// increment(number: &10)  // エラー!

2. &(アンパサンド)を忘れずに

inoutパラメータを渡すときは、必ず&をつける必要があります。

var value = 10

// 正しい
increment(number: &value)

// エラー
// increment(number: value)  // &がないのでエラー

3. 同じ変数を複数のinoutパラメータに渡せない

同じ変数を同時に複数のinoutパラメータとして渡すことはできません。

func addValues(a: inout Int, b: inout Int) {
    a = a + b
}

var value = 5
// addValues(a: &value, b: &value)  // エラー!

4. グローバル変数やプロパティとの競合に注意

inoutパラメータとして渡した変数は、関数実行中に他の方法でアクセスすることができません。

var globalValue = 10

func modifyGlobal(value: inout Int) {
    value += 1
    // print(globalValue)  // 実行中は直接アクセスできない
}

// modifyGlobal(value: &globalValue)

inoutとreturnの使い分け

多くの場合、inoutを使わずに戻り値を返す方法でも同じことができます。どちらを使うべきでしょうか?

returnを使う方法

func doubled(number: Int) -> Int {
    return number * 2
}

var value = 5
value = doubled(number: value)
print(value)  // 10

inoutを使う方法

func double(number: inout Int) {
    number *= 2
}

var value = 5
double(number: &value)
print(value)  // 10

どちらを選ぶべきか

returnを使うべき場合

  • 1つの値を返すだけの場合
  • 関数型プログラミングのスタイルを重視する場合
  • 元の値を保持したい場合

inoutを使うべき場合

  • 複数の値を変更する必要がある場合
  • 大きなデータ構造のコピーを避けたい場合(パフォーマンス向上)
  • 標準ライブラリの関数(swapなど)との一貫性を保つ場合

一般的に、Swiftでは戻り値を使う方が推奨されています。inoutは必要なときだけ使うようにしましょう。

inoutのパフォーマンス面でのメリット

大きなデータ構造を扱う場合、inoutはパフォーマンス面で有利になることがあります。

struct LargeData {
    var items: [Int] = Array(repeating: 0, count: 10000)
}

// 値渡し:データ全体をコピー
func processWithCopy(data: LargeData) -> LargeData {
    var data = data
    data.items[0] = 999
    return data
}

// inout:コピーなし
func processWithInout(data: inout LargeData) {
    data.items[0] = 999
}

inoutを使うと、データのコピーが発生しないため、メモリ効率が良くなります。

よくある間違いと解決法

間違い1:定数に使おうとする

let constant = 5
// increment(number: &constant)  // エラー

解決法: 変数として宣言する

var variable = 5
increment(number: &variable)  // OK

間違い2:&を忘れる

var value = 5
// increment(number: value)  // エラー

解決法: &をつける

increment(number: &value)  // OK

間違い3:関数内で不要なvarを使う

// 不要な書き方
func increment(number: inout Int) {
    var number = number  // 不要!
    number += 1
}

解決法: inoutパラメータはそのまま使える

func increment(number: inout Int) {
    number += 1  // これでOK
}

実務での活用例

データベースレコードの更新

struct User {
    var name: String
    var email: String
    var age: Int
}

func updateUserProfile(user: inout User, newEmail: String, incrementAge: Bool) {
    user.email = newEmail
    if incrementAge {
        user.age += 1
    }
}

var currentUser = User(name: "太郎", email: "old@example.com", age: 25)
updateUserProfile(user: &currentUser, newEmail: "new@example.com", incrementAge: true)

ゲーム開発でのプレイヤー状態管理

struct Player {
    var health: Int
    var score: Int
    var level: Int
}

func takeDamage(player: inout Player, damage: Int) {
    player.health -= damage
    if player.health <= 0 {
        player.health = 0
    }
}

func addScore(player: inout Player, points: Int) {
    player.score += points
    if player.score >= 100 {
        player.level += 1
        player.score = 0
    }
}

まとめ

Swiftのinoutは、関数のパラメータを参照渡しにするための強力な機能です。重要なポイントをおさらいしましょう。

inoutの特徴

  • 関数内での変更が呼び出し元に反映される
  • パラメータの型の前にinoutキーワードを記述
  • 呼び出し時には変数の前に&をつける
  • 変数のみ渡せる(定数やリテラルは不可)

使い分けの基準

  • 基本的には戻り値を使う方が推奨
  • 複数の値を変更する場合や大きなデータ構造を扱う場合にinoutを検討
  • パフォーマンスが重要な場面ではinoutが有利

注意点

  • &を忘れない
  • 定数には使えない
  • 同じ変数を複数のinoutパラメータに渡せない

inoutは便利な機能ですが、使いすぎると可読性が下がることもあります。適切な場面で使用することで、より効率的でわかりやすいSwiftコードを書くことができます。

まずは簡単な例から試してみて、徐々に実践的な場面で活用していきましょう。

プログラミングの独学におすすめ
プログラミング言語の人気オンラインコース
独学でプログラミングを学習している方で、エラーなどが発生して効率よく勉強ができないと悩む方は多いはず。Udemyは、プロの講師が動画で実際のプログラムを動かしながら教えてくれるオンライン講座です。講座の価格は、セール期間中には専門書籍を1冊買うよりも安く済むことが多いです。新しく学びたいプログラミング言語がある方は、ぜひUdemyでオンライン講座を探してみてください。
目次