Мазмунга өтүү

Жылдыруу семантикасы: терең кароо

Сабактын башталышы

Жылдыруу семантикасы: терең кароо

Ресурстарды көчүрбөстөн уурдоо - жана муну коопсуз жасоо

Негизги идея: көчүрүү объекттин ресурстарын кайталайт; жылдыруу болсо ошол ресурстардын ээлигин булактан кабылдагычка өткөрүп берип, булакты жарактуу бирок бош абалда калтырат. Булак убактылуу объект болгондо же std::move аркылуу ачык кастинг жасалганда, компилятор кымбат көчүрүүнүн ордуна арзан жылдыруу жолун тандай алат. Туура колдонулса, жылдыруу семантикасы O(n) терең көчүрүүлөрдү O(1) көрсөткүч алмашууга айлантат - чакырган код өзгөрбөйт.
Теманын аягында сиз:
  • маани категорияларын окуп, T&& rvalue-шилтемеси качан байланарын так билесиз;
  • туура жылдыруу конструкторун жана жылдыруу менчиктөө операторун жаза аласыз;
  • аларды noexcept деп белгилөө программанын убадасын гана эмес, өндүрүмдүүлүгүн да өзгөртөрүн түшүндүрө аласыз;
  • беш эреже колдоно аласыз (жана нөл эрежесин артык көрөсүз);
  • аныкталбаган жүрүм-турумга алып келбестен жылдырылгандан кийинки абал тууралуу ой жүгүртө аласыз.

1. Маани категориялары жана rvalue-шилтемелер

C++ тилиндеги ар бир туюнтманын түрү да, маани категориясы да бар. Практикалык жылдыруу семантикасы үчүн негизги бөлүнүү lvalue - аты жана & аркылуу алса боло турган туруктуу дареги бар нерселер - жана rvalue - убактылуу жана башка объекттер, алардын ресурстарын коопсуз алса болот, себеби аларды эч ким кайра көрбөйт - ортосунда.

rvalue-шилтеме, T&& деп жазылат, ал бир гана rvalue менен байланышат. Бүт амал ушунда: T&& параметри бар ашыкча жүктөө так убакыты бүткөн маани аргумент болгондо тандалат, ошондуктан ошол ашыкча жүктөөнүн ичинде аны уурдоо коопсуз.

void f(const std::string&  s);  // lvalue ашыкча жүктөө: баарын алат, уурдоого болбойт
void f(std::string&&        s);  // rvalue ашыкча жүктөө: убактылууну алат, уурдаса болот

std::string name = "Ada";
f(name);              // f(const std::string&) чакырат  - name бул lvalue
f("Ada");             // f(std::string&&) чакырат        - убактылуу бул rvalue
f(std::move(name));   // f(std::string&&) чакырат        - name кайра керек эмес деп УБАДА беребиз

std::move эч нерсени жылдырбайт. Бул кастинг: ал өз аргументине rvalue-шилтеме чыгарат, ошентип жылдыруу ашыкча жүктөөсү тандалат. Иштин өзү тандалган жылдыруу конструкторунда же жылдыруу менчиктөөдө болот. std::move дегенди "муну убакыты бүтүп жаткандай кара" деп ойлоңуз - жылдырууну кастинг эмес, түрдүн өзү аткарат.

Аты бар rvalue-шилтеме өзү lvalue болуп саналат. void g(std::string&& s) ичинде s параметринин аты бар, ошондуктан андан жылдыруу үчүн кайрадан std::move(s) жазуу керек. Муну унутсаңыз, унчукпай көчүрүү болуп калат.

Бул сабакты YourAIZone платформасында улантыңыз

Толук сабакта — толук түшүндүрмө, чыгарылган мисалдар, көп кездешкен каталар, заматта текшерилүүчү тесттер жана ЖИ-репетитор. Конок катары дароо баштаңыз же прогрессти сактоо үчүн аккаунт түзүңүз.

Толук сабакта

  • Толук түшүндүрмө
  • Чыгарылган мисалдар
  • Көп кездешкен каталар жана алардан кантип качуу керек
  • Тест суроолору: 15
  • Тема боюнча суроолорго жооп берген ЖИ-репетитор
  • Окуучу, ата-эне жана мугалим үчүн прогрессти көзөмөлдөө