みーのぺーじ

みーが趣味でやっているPCやソフトウェアについて.Python, Javascript, Processing, Unityなど.

コピーするときの動作

変数aに文字列「これはテストです.」があり,これを変数bにコピーする,という動作には3つの選択肢があります.

aとbが同じオブジェクトを参照する

代表的な言語はPythonです.

a = "これはテストです."
b = a
print("a={}, id={}".format(a, id(a)))
print("b={}, id={}".format(b, id(b)))

これを実行すると,下記のようになります.aとbが同じオブジェクトを参照していることが分かります.

a=これはテストです., id=1933243856048
b=これはテストです., id=1933243856048

ただし,複数の変数が同じオブジェクトを参照していると,オブジェクトを開放するタイミングが複雑になります.

a = "これはテストです."
b = a
print("a={}, id={}".format(a, id(a)))
del a # aを開放
print("b={}, id={}".format(b, id(b)))

変数aを削除する行を追加しました.

a=これはテストです., id=2623329744048
b=これはテストです., id=2623329744048

変数bの参照が残っているので,変数aを削除する際に,文字列「これはテストです.」を開放できない状況です.Pythonはこれをうまく処理してくれます.

そんなややこしいことはするなとエラーにする

Rustではエラーになります.

fn main() {
    let a: String = String::from("これはテストです.");
    let b = a;
    println!("a = {}", a);
    println!("b = {}", b);
}

これを実行すると,コンパイル時にエラーとなります.

error[E0382]: borrow of moved value: `a`

Rustでは1つのオブジェクトの所有権は1個だけ,という規則があり,安全なメモリ管理をしています.

オブジェクトを複製する

上記の例を実行するには,明示的にオブジェクトを複製します.

fn main() {
    let a: String = String::from("これはテストです.");
    let b = a.clone(); // 複製
    println!("a = {}", a);
    println!("b = {}", b);
}

正常に実行されます.

a = これはテストです.
b = これはテストです.