Cairoのスマートポインターは、通常のポインターに安全機能を追加することで、安全で効率的なメモリ管理を実現する高度なデータ構造です。nullポインターの参照解除や、初期化されていないメモリへのアクセスといったよくある問題を防ぎます。
スマートポインターは通常のポインターと同じように振る舞いますが、所有権を追跡し、安全なメモリアクセスを保証することで、nullポインターやダングリングポインターの参照解除といった問題を防ぎます。
Cairoには、Box<T>やNullable<T>のようないくつかのスマートポインター型があります。
Box<T>: データを特別なメモリセグメントに保存するもので、大きなデータや動的にサイズが変わるデータに最適です。データをコピーせずに所有権を移すことができます。Nullable<T>: 型Tの有効な値かnullのどちらかを指し、省略可能な値を扱うのに便利です。スマートポインターは安全でないメモリアクセスを防ぐのに役立ち、不要になったメモリが自動的に解放されるようにすることで、メモリリークのリスクを減らします。
Box<T>を使うBox<T>のようなスマートポインターを使うと、二分木のような再帰的な型を、メモリを効率的に割り当て、無限再帰を避けることで安全に扱えます。
use core::box::{BoxTrait};
#[derive(Copy, Drop)]
enum BinaryTree {
Leaf: u32,
Node: (u32, Box<BinaryTree>, Box<BinaryTree>),
}
fn main() {
let leaf1 = BinaryTree::Leaf(1);
let leaf2 = BinaryTree::Leaf(2);
let node = BinaryTree::Node((3, BoxTrait::new(leaf1), BoxTrait::new(leaf2)));
println!("{:?}", node);
}
スマートポインターは、大きな構造体をコピーするのではなくデータへの参照を渡すことで、メモリのオーバーヘッドを減らし、パフォーマンスを向上させます。
// `Cart` is a large struct that contains a lot of information
fn pass_pointer(cart: Box<Cart>) {
let cart = cart.unbox();
println!("{} is shopping today and bought {} items", cart.buyer, cart.items);
}
Chrono Realmsでは、Time Keepersはタイムラインの木だけでなく、Chrono Chainも扱います。Chrono Chainとは、連なったTimeNodeの並びで、それぞれが特定の瞬間を表します。 Chrono Chainは、連続する瞬間がまっすぐにつながった道筋で、それぞれのTimeNodeが次のノードにつながっています。 このChrono Chainは、一連の特定の出来事をたどっていくときに役立ちます。Time Keepersが1本のタイムラインを追えるようになるからです。
しかし、こうした長くなる可能性のあるChrono Chainを扱うために、Time KeepersはSmart Pointers (Box<t>)<strong>を使い、瞬間のリストを安全に管理してたどります。不要なメモリの複製やオーバーフローを起こさないためです。 それぞれの</strong>TimeNode</t>は次のノードへの参照を持ち、再帰的な構造を作ります。
見習いとしての課題は、スマートポインターを使ってChrono Chainを再帰的なリスト構造として実装することです。
この演習では、次のことを行います。
ChronoChain列挙型を作成します。Box<T>スマートポインターを使います。u32の値の配列からChronoChainを作る関数を実装します。ChronoChainをたどり、リストに格納された値の合計を求める関数を実装します。ChronoChain列挙型を定義する2つのバリアントを持つ再帰的な列挙型ChronoChainを作成します。
End:リストの終わりを表します。Link:u32の値と、チェーン内の次のノードへのボックス化された参照を持ちます。u32の値の配列を受け取り、ChronoChainを返すChronoChain::build関数を書きます。値はスマートポインターを使って順番につなぎます。
ChronoChainを再帰的にたどり、すべてのノードの値の合計を求めるChronoChain::sum関数を書きます。
fn main() {
// Create a ChronoChain from an array of values
let chrono_chain = ChronoChain::build(array![10, 20, 30]);
// Sum the values in the ChronoChain
let total_sum = chrono_chain.sum();
println!("Total Time Power: {}", total_sum);
}