Moveのすべての変数にはスコープと所有者があります。スコープは変数が有効なコードの範囲であり、所有者はこの変数が属するスコープです。所有者のスコープが終了すると、変数は削除されます。これはMoveの基本的な概念であり、その動作を理解することが重要です。

所有権

関数スコープで定義された変数は、このスコープによって所有されます。ランタイムは関数スコープを通過し、すべての式とステートメントを実行します。関数スコープが終了すると、その中で定義された変数は削除または解放されます。

module book::ownership {
    public fun owner() {
        let a = 1; // aは`owner`関数によって所有される
    } // aはここで削除される

    public fun other() {
        let b = 2; // bは`other`関数によって所有される
    } // bはここで削除される

    #[test]
    fun test_owner() {
        owner();
        other();
        // aとbはここでは無効
    }
}

上記の例では、変数aowner関数によって所有され、変数bother関数によって所有されます。これらの関数が呼び出されると、変数が定義され、関数が終了すると変数が破棄されます。

値の返却

owner関数を変更して変数aを返すようにすると、aの所有権は関数の呼び出し元に移ります。

module book::ownership {
    public fun owner(): u8 {
        let a = 1; // aはここで定義される
        a // スコープが終了し、aが返される
    }

    #[test]
    fun test_owner() {
        let a = owner();
        // aはここで有効
    } // aはここで削除される
}

値渡し

さらに、変数aを別の関数に渡すと、aの所有権はこの関数に移ります。この操作を行うとき、値をあるスコープから別のスコープに「移動」します。これを「ムーブセマンティクス」とも呼びます。

module book::ownership {
    public fun owner(): u8 {
        let a = 10;
        a
    } // aは返される

    public fun take_ownership(v: u8) {
        // vは`take_ownership`によって所有される
    } // vはここで削除される

    #[test]
    fun test_owner() {
        let a = owner();
        take_ownership(a);
        // aはここでは無効
    }
}

ブロックによるスコープ

各関数にはメインスコープがあり、ブロックを使用してサブスコープを持つこともできます。ブロックはステートメントと式のシーケンスであり、それ自身のスコープを持ちます。ブロックで定義された変数はこのブロックによって所有され、ブロックが終了すると変数は削除されます。

module book::ownership {
    public fun owner() {
        let a = 1; // aは`owner`関数のスコープによって所有される
        {
            let b = 2; // bはブロックによって所有される
            {
                let c = 3; // cはブロックによって所有される
            }; // cはここで削除される
        }; // bはここで削除される
        // a = b; // エラー: bはここでは無効
        // a = c; // エラー: cはここでは無効
    } // aはここで削除される
}

しかし、ブロックの戻り値を使用する場合、変数の所有権はブロックの呼び出し元に移ります。

module book::ownership {
    public fun owner(): u8 {
        let a = 1; // aは`owner`関数のスコープによって所有される
        let b = {
            let c = 2; // cはブロックによって所有される
            c // cが返される
        }; // cはここで削除される
        a + b // aとbはここで有効
    }
}

コピー可能な型

Moveの一部の型は「コピー可能」であり、所有権を移さずにコピーできます。これは、整数やブール値のように小さくてコピーが安価な型に便利です。Moveコンパイラは、これらの型が関数に渡されたり、関数から返されたり、スコープに「移動」されて元のスコープでアクセスされたりするときに自動的にコピーします。

参考文献