3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Rustで値を交換する

Last updated at Posted at 2022-08-22

はじめに

Rustで値を交換する方法を調べたのでまとめました。

2つの変数の値を交換

以下の様に変数xと変数yがあるとします。
2つの変数の値をどのように交換すればよいでしょうか。

let mut x = String::from("ABC");
let mut y = String::from("DEF");

すぐ思いつくのが一時変数を使用して交換する方法です。

let tmp = x;
x = y;
y = tmp;

Rustでは変数の値を別の変数に代入すると所有権の移動が発生します。
すると元の変数は未初期化状態になり使えなくなりますが、値を再代入することで使用可能になります。
※プリミティブ型は自動的に値がコピーされるため所有権の移動は発生しません

また、タプルを使用した方法だと1行で交換できます。
この方法だと変数xと変数yが一時的に未初期化状態になり値が再代入されます。

(x, y) = (y, x);

変数を未初期化状態にせずに値を交換するにはstd::mem::swap関数を使います。
引数には変数の可変参照を渡します。

std::mem::swap(&mut x, &mut y);

Option::Someの中身と変数の値を交換

次に片方の変数がOption型の場合を考えます。

let mut x = String::from("ABC");
let mut y = Some(String::from("DEF"));

一時変数とタプルを使った交換方法は以下の通りです。
Option型の中身を取り出すにはunwrap関数を呼び出します。

一時変数

let tmp = Some(x);
x = y.unwrap();
y = tmp;

タプル

(x, y) = (y.unwrap(), Some(x));

次にstd::mem::swap関数を使った交換を考えます。

std::mem::swap(&mut x, &mut y.unwrap());

しかし上記のコードは正しく動作しません。
unwrap関数を呼び出すと所有権の移動が発生するからです。
上記のコードの場合、変数xには文字列DEFが移動しますが
変数yは未初期化状態になっています。

所有権を移動させずに中身の可変参照を取得するにはas_mut関数を呼び出します。
as_mut関数はOption<T>からOption<&mut T>の変数を生成して返します。
不変参照の場合はas_ref関数を呼び出します。

よって正しく動作するコードは以下の通りです。

std::mem::swap(&mut x, y.as_mut().unwrap());

配列内の要素を交換

次に配列やベクタ内の要素を交換する方法を考えます。

let mut ary = [String::from("ABC"), String::from("DEF")];

この場合は一時変数やタプルを使用した交換はできません。
配列やベクタの要素は未初期化状態になるのが禁止されているからです。

一時変数

let tmp = ary[0]; // ary[0]が未初期化状態になるのでコンパイルエラー
ary[0] = ary[1];
ary[1] = tmp;

タプル

(ary[0], ary[1]) = (ary[1], ary[0]); // ary[0]とary[1]が未初期化状態になるのでコンパイルエラー

std::mem::swap関数を使った交換もできません。
特定の変数に対する可変参照は複数存在できないからです。

std::mem::swap(&mut ary[0], &mut ary[1]); // 変数aryに対する可変参照が2つあるのでコンパイルエラー

配列やベクタには専用のswap関数が存在します。
交換したい要素のインデックスを指定します。

ary.swap(0, 1);

まとめ

  • 2つの変数の値を交換するには以下の方法がある
    • 一時変数を使用する
    • タプルを使用する
    • std::mem::swap関数を使用する
  • 配列やベクタの要素は専用のswap関数でしか交換できない

参考文献

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?