Հասկանալով փոխառությունը ժանգով


Փոխառությունը բարդ թեմա է՝ կապված սեփականության հետ։ Դա հասկանալը կարևոր է Rust-ում հիշողության կառավարման հետ աշխատելու համար:

Rust-ը օգտագործում է փոխառության ստուգիչ՝ իր սեփականության կանոնները պահպանելու և ծրագրերի հիշողության անվտանգությունն ապահովելու համար: Սեփականության կանոնները թելադրում են, թե ինչպես է Rust-ը կառավարում հիշողությունը կույտի և կույտի վրա:

Rust ծրագրեր գրելիս պետք է օգտագործեք փոփոխականներ՝ չփոխելով համապատասխան արժեքի սեփականությունը: Rust-ն ապահովում է փոխառության կայուն մեխանիզմ՝ խրախուսելու ճկունությունը և կոդի վերօգտագործումը:

Ի՞նչ է ժանգով փոխառությունը:

Փոխառությունը փոփոխականի արժեքին մուտք գործելն է՝ առանց փոփոխականին սեփականության իրավունք վերցնելու՝ սեփականատիրոջը հղում անելով: Փոխառության ստուգիչն ապահովում է, որ հղումը վավեր է, և տվյալները չեն հեռացվում՝ օգտագործելով կյանքի ժամկետներ կոչվող կառուցվածքը:

Կյանքի ժամկետն այն է, թե որքան երկար է գոյություն ունի փոփոխականը: Կյանքի տևողությունը սկսվում է փոփոխականների ստեղծմամբ և ավարտվում փոփոխական ոչնչացմամբ: Դուք կարող եք փոխառել փոփոխականի սեփականությունը, և երբ փոխառված հղումը դուրս է գալիս շրջանակից, սեփականության իրավունքը վերադառնում է սեփականատեր փոփոխականին: Փոխառությունը մի փոքր նման է այն ցուցիչներին, որոնք դուք կգտնեք այնպիսի լեզուներում, ինչպիսիք են C++-ը և Go-ն: Բայց Rust կոմպիլյատորն օգտագործում է փոխառության ստուգիչը՝ ապահովելու ծրագրերի հիշողության անվտանգությունը:

Ժանգով փոխառության օրինակ

Դուք կարող եք փոխառել փոփոխականի սեփականությունը՝ հղում կատարելով սեփականատիրոջը՝ օգտագործելով նշան (&) նշանը:

fn main() {
    let x = String::from("hello"); // x owns "hello"
    let y = &x; // y references x, borrows "hello"
    println!("{}", x); 
    println!("{}", y)
}

Առանց հղում անելով պարտք վերցնելու՝ ծրագիրը խուճապի կմատնվեր։ Դա կխախտի սեփականության կանոնը, ըստ որի արժեքը կարող է ունենալ մեկ սեփականատեր, և երկու փոփոխականները չեն կարող մատնանշել նույն հիշողության վայրը: Փոխառությունը կարող է շատ օգտակար լինել գործառույթների մեջ: Ահա ֆունկցիայի մեջ փոխառելու օրինակ՝ սեփականության իրավունքը պահպանելու համար՝ միաժամանակ կանչելով այլ գործառույթներ, որոնք որպես արգումենտ ընդունում են տեղական փոփոխականները:

fn print_even(vectr: &Vec<i32>) {
    for values in vectr {
        if values % 2 == 0 {
            println!("{}", values);
        }
    }
}

print_even ֆունկցիան որպես արգումենտ հղում է անում 32-բիթանոց ամբողջ թվերի վեկտորին: Այնուհետև այն տպում է արժեքների տողեր, որոնք վեկտորում երկուսի բազմապատիկ են՝ օգտագործելով for-loop և println! մակրո.

fn main() {
    let number_vector = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
    print_even(&number_vector); // ownership is borrowed, not moved
    println!("The main function retains ownership of the number vector{:?}", number_vector)
}

Հիմնական ֆունկցիան հայտարարում է number_vector փոփոխականը և դրան վերագրում է 32-բիթանոց ամբողջ թվերի վեկտոր։ Այնուհետև այն կանչում է print_even ֆունկցիան և այն հղում է փոխանցում number_vector փոփոխականին՝ օգտագործելով ամպերսանդի նշանը:

Հիմնական ֆունկցիան պահպանում է number_vector փոփոխականի սեփականությունը, այն կարող է շարունակել օգտագործել արժեքը իր հիշողության վայրում:

Փոխառություն և փոփոխվող հղումներ

Գործառույթները կարող են նաև փոփոխել փոխառված փոփոխականները՝ օգտագործելով դրանց փոփոխվող հղումները՝ նախքան սեփականության իրավունքը վերադարձնելը:

Այնուամենայնիվ, ի տարբերություն սովորական փոփոխականների, որոնք կարող են mutable-ի սահմանվել՝ օգտագործելով mut բանալի բառը, դուք պետք է փոփոխական հղումները նախածանցի դրեք ամպերսանդի նշանով:

Նախքան փոփոխական հղումներ կատարելը, փոփոխականը, որը ցանկանում եք փոփոխել, պետք է փոփոխական լինի:

fn remove_value(vectr: &mut Vec<i32>) -> &Vec<i32> {
    vectr.remove(4);
    return vectr
}

remove_value ֆունկցիան ընդունում է 32-բիթանոց ամբողջ թվերի փոփոխվող վեկտորի հղումը: Այն վերադարձնում է 32-բիթանոց ամբողջ թվերի վեկտորը չորրորդ ինդեքսի վեկտորի արժեքը հեռացնելուց հետո:

fn main() {
    let mut nums = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
    remove_value(&mut nums); // mutable reference here
    println!("{:?}", nums); 
}

Ֆունկցիան փոփոխում է nums վեկտորը՝ կանչելով remove_value և որպես արգումենտ փոխանցելով վեկտորի փոփոխվող հղումը։ Վեկտորը տպելիս վեկտորի նախորդ չորրորդ ինդեքսը գոյություն չունի:

Ուշադրություն դարձրեք, որ արգումենտը հղում է փոփոխական վեկտորին:

Կարևոր է հասկանալ սեփականության իրավունքը և փոխառությունը

Դուք պետք է հասկանաք սեփականության իրավունքը և փոխառությունը, որպեսզի գրեք արդյունավետ, հիշողության համար անվտանգ Rust կոդը, որը հավաքվում և գործարկվում է: Եթե ձեր կոդը չի հետևում սեփականության կանոններին, ապա պարտքի ստուգիչը կհայտնաբերի այն: Դուք պետք է ձեր ծրագիրը ապահով դարձնեք հիշողության մեջ, որպեսզի Rust-ը այն կազմի:

Փոխառության ստուգիչը նյարդայնացնում է, երբ դուք նոր եք Rust-ում: Բայց քանի որ ավելի շատ Rust կոդ եք գրում, դուք կվարժվեք դրան և փորձ ձեռք կբերեք հիշողության համար անվտանգ Rust կոդ գրելու հարցում: