<Box<T
Box
یک اشارهگر مالک به دادههای روی heap است:
fn main() { let five = Box::new(5); println!("five: {}", *five); }
<Box<T
ویژگی <Deref<Target = T
را پیادهسازی میکند، که به این معناست که میتوانید مستقیم روشهای T
را روی <Box<T
فراخوانی کنید.
تایپهای دادههای بازگشتی یا انواع داده با اندازههای دینامیک را نمیتوان به صورت inline بدون pointer indirection ذخیره کرد، که میتوان با استفاده از Box
آن کار را کرد:
#[derive(Debug)] enum List<T> { /// A non-empty list: first element and the rest of the list. Element(T, Box<List<T>>), /// An empty list. Nil, } fn main() { let list: List<i32> = List::Element(1, Box::new(List::Element(2, Box::new(List::Nil)))); println!("{list:?}"); }
-
Box
مانندstd::unique_ptr
در ++C است، با این تفاوت که تضمین شده است که هیچگاه تهی (null) نخواهد بود. -
Box
میتواند زمانی مفید باشد که شما:- یک تایپ دارید که اندازه آن در زمان کامپایل مشخص نیست، اما کامپایلر Rust نیاز به دانستن اندازه دقیق آن دارد.
- میخواهید مالکیت مقدار زیادی داده را انتقال دهید. برای جلوگیری از کپی کردن حجم زیادی از دادهها در پشته، به جای آن دادهها را در heap در یک
Box
ذخیره کنید تا فقط اشارهگر منتقل شود.
-
اگر از
Box
استفاده نمیکردیم و سعی میکردیم یکList
را مستقیماً در داخلList
قرار دهیم، کامپایلر نمیتوانست اندازه ثابتی برای ساختار در حافظه محاسبه کند (زیراList
اندازهای بینهایت پیدا میکرد). -
Box
این مشکل را حل میکند زیرا اندازهای برابر با یک اشارهگر عادی دارد و فقط به عنصر بعدیList
در heap اشاره میکند. -
Box
را از تعریفList
حذف کنید و خطای کامپایلر را نمایش دهید. پیام خطا "recursive without indirection" را دریافت خواهیم کرد، زیرا برای رکورسیون دادهها باید از یک روش غیرمستقیم، مانندBox
یا ارجاعی از نوعی، به جای ذخیره مستقیم مقدار استفاده کنیم.
برای کاوش بیشتر
بهینه سازی Niche
اگرچه Box
مشابه std::unique_ptr
در ++C به نظر میرسد، اما نمیتواند خالی/null باشد. این ویژگی باعث میشود که Box
یکی از تایپهایی باشد که به کامپایلر اجازه میدهد ذخیرهسازی برخی از enum
ها را بهینهسازی کند.
برای مثال، <<Option<Box<T
همان اندازه را دارد که <Box<T
، زیرا کامپایلر از مقدار NULL برای تمایز بین variant ها به جای استفاده از تگ صریح استفاده میکند ("بهینهسازی اشارهگر خالی"):
use std::mem::size_of_val; struct Item(String); fn main() { let just_box: Box<Item> = Box::new(Item("Just box".into())); let optional_box: Option<Box<Item>> = Some(Box::new(Item("Optional box".into()))); let none: Option<Box<Item>> = None; assert_eq!(size_of_val(&just_box), size_of_val(&optional_box)); assert_eq!(size_of_val(&just_box), size_of_val(&none)); println!("Size of just_box: {}", size_of_val(&just_box)); println!("Size of optional_box: {}", size_of_val(&optional_box)); println!("Size of none: {}", size_of_val(&none)); }