#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *a = malloc(1);
free(a); // 開放
char *b = malloc(1);
*b = 'b';
*a = 'a'; // ダングリングポインタへの操作
printf("%c", *b); // "a" ("b"ではない!?)
}
Rustは以下の3つの概念を用いることで
GC無しで安全なメモリ管理を提供する
fn foo() {
let v = vec![1, 2, 3]; // 変数束縛
let v2 = v; // 所有権がvからv2に変更される
println!("{}", v); // ここでvを参照しようとするとコンパイルエラー
}
// v2がスコープから外れるのでメモリも解放される
// 値渡し、所有権も移る
fn foo(v1: Vec<i32>, v2: Vec<i32>) -> i32){
// v1とv2についての作業を行う
42
}
let v1 = vec![1, 2, 3];
let v2 = vec![1, 2, 3];
let answer = foo(v1, v2);
// 所有権が移動したのでv1、v2をここで使用するとコンパイルエラー
fn foo(v1: Vec<i32>, v2: Vec<i32>) -> (Vec<i32>, Vec<i32>, i32) {
// v1とv2についての作業を行う
// 所有権と関数の結果を返す
(v1, v2, 42)
}
let v1 = vec![1, 2, 3];
let v2 = vec![1, 2, 3];
let (v1, v2, answer) = foo(v1, v2);
// 所有権を借りる
fn foo(v1: &Vec<i32>, v2: &Vec<i32>) -> i32 {
// v1とv2についての作業を行う
// 答えを返す
42
}
let v1 = vec![1, 2, 3];
let v2 = vec![1, 2, 3];
let answer = foo(&v1, &v2);
// ここではv1とv2が使える!
{
let r;
{
let x = 1;
r = &x;
// ここまでがxの有効なスコープ
}
assert_eq!(*r, 1); // xのスコープ外で参照しているのでコンパイルエラー
}
enum Option<T> {
None,
Some(T)
}
// ScalaのEitherみたいなやつ
enum Result<T, E> {
Ok(T),
Err(E),
}
enum Message {
Quit,
ChangeColor(i32, i32, i32),
Move { x: i32, y: i32 },
Write(String),
}
// x: i32
match x {
1 | 2 => println!("one or two"),
3 => println!("three"),
_ => println!("anything"),
}
// x : Option<t>
match x {
None => false,
Some(_) => true
}
trait HasArea {
fn area(&self) -> f64;
}
impl HasArea for i32 {
fn area(&self) -> f64 {
println!("this is silly");
*self as f64
}
}
5.area();
let plus_one = |x: i32| x + 1;
assert_eq!(2, plus_one(1));