Rust زبان قدرتمندی است، با برخی رفتارهای پیچیده و منحصر به فرد. مالکیت مفهومی است که درک درست آن حیاتی است.
زبان های برنامه نویسی در نحوه مدیریت حافظه و اجرای قوانین مدیریت حافظه متفاوت هستند. Go و Python از زباله گردها استفاده می کنند، بنابراین توسعه دهندگان می توانند روی نوشتن کد تمرکز کنند. C و C++ به برنامه نویسان مسئولیت مدیریت حافظه در سطح پایین تری را می دهند.
Rust با مدیریت حافظه متفاوت رفتار می کند و از مفاهیمی استفاده می کند که آن را مالکیت و قرض می نامد. از یک “بررسی کننده قرض” برای تقویت ایمنی حافظه به طور موثر استفاده می کند.
مالکیت چیست؟
مالکیت یک ویژگی و قرارداد Rust است که به اطمینان از ایمنی حافظه برنامههای بدون زبالهگیر کمک میکند. این راه دیگری برای مقابله با مشکل نشت حافظه در کد شما است.
کامپایلر Rust بررسی می کند که آیا برنامه در زمان کامپایل از قوانین مالکیت پیروی می کند. اگر برنامه از این قوانین پیروی کند، می تواند اجرا شود. اگر اینطور نباشد، کامپایلر از تولید یک فایل اجرایی امتناع می کند.
Rust قوانین مالکیت را با استفاده از چک کننده قرض تأیید می کند. بررسی کننده قرض مدل مالکیت را تأیید می کند و تصمیم می گیرد که آیا یک مقدار در حافظه (پشته یا پشته) خارج از محدوده است یا خیر. اگر مقداری خارج از محدوده خود باشد، برای سایر قسمت های برنامه قابل دسترسی نیست مگر اینکه قرض گرفته شده باشد.
قوانین مالکیت
در Rust، هر متغیری دارای مقداری است که با آن مقداردهی اولیه شده است و فقط یک مالک میتواند وجود داشته باشد. هنگامی که مالک خارج از محدوده باشد، مقدار حذف می شود. درک جزئیات قوانین مالکیت مهم است.
اولین قانون مالکیت این است که هر متغیر دارای مقدار اولیه خود است.
let owner = String::from("one");
متغیر مالک بالا دارای رشته یک است و برخلاف زبانهایی مانند Python و Go، این مقدار در هنگام تخصیص مجدد متغیر حذف میشود.
دومین قانون مالکیت این است که دو متغیر نمی توانند به یک مکان حافظه اشاره کنند. هر ارزشی می تواند تنها یک مالک داشته باشد.
let new_owner = owner;
متغیر new_owner اکنون دارای مقدار ذخیره شده در محل حافظه متغیر مالک است. اگر سعی کنید از متغیر مالک استفاده کنید، کامپایلر دچار وحشت می شود و از تولید فایل اجرایی خودداری می کند.
در اکثر زبان هایی که از زباله گردها استفاده می کنند، دو متغیر می توانند به یک مکان حافظه اشاره کنند. در اینجا نمونه ای از کد جاوا اسکریپت معادل آورده شده است:
let owner = "owner";
let new_owner = owner;
console.log(new_owner);
اجرای کد جاوا اسکریپت بالا بدون خطا کار می کند و اگر همین کار را در Go یا Python انجام دهید، برنامه شما نیز بدون خطا کار می کند.
سومین قانون مالکیت این است که وقتی یک متغیر از محدوده اعلام شده خارج شد، مقدار حذف می شود و حافظه تخصیص داده می شود.
// a variable in a separate scope
{
let example = String::from("Here's a new scope");
}
print!("{}", example)
شما نمی توانید به متغیر مثال خارج از محدوده آن دسترسی پیدا کنید. تلاش برای انجام این کار باعث وحشت کامپایلر می شود.
مالکیت در توابع
وقتی یک مقدار را به عنوان آرگومان به یک تابع میفرستید، تابع میتواند به آن متغیر دسترسی داشته باشد، حتی اگر در محدوده آن تعریف نشده باشد:
fn printer(value: String) -> String {
return value
}
fn main() {
let x = String::from("Prints a value"); // x owns the string value
// ownership is moved to the printer function here
print!("{} The Result of Printing X is that it -:", printer(x));
}
تابع می تواند به آن متغیر دسترسی داشته باشد زیرا Rust مالکیت آن را در زمان کامپایل به تابع منتقل می کند.
ممکن است فکر کنید هنوز امکان استفاده از متغیر بعداً در محدوده اصلی آن وجود دارد:
fn printer(value: String) -> String {
return value
}
fn main() {
let x = String::from("Prints a value");
print!("{} The Result of Printing x is that it -:", printer(x));
// Trying to use the variable after ownership of its value has been transferred
println!("{} shouldn't be accessible", x)
}
اما اگر این کار را امتحان کنید، کامپایلر دچار وحشت می شود و از تولید یک فایل اجرایی امتناع می کند:
Rust قابلیت استفاده مجدد کد را در اولویت قرار می دهد
قابلیت استفاده مجدد کد یک عمل ضروری است، اما برای تمرین قابلیت استفاده مجدد کد باید قوانین مالکیت Rust را درک کنید.
Rust یک زبان برنامه نویسی بسیار انعطاف پذیر است. مفاهیمی مانند قرض گرفتن، جابجایی، کپی کردن، و مالکیت شبیه سازی را برای قابلیت استفاده مجدد متغیر فراهم می کند.