Мавзу: С++ да кўрсаткичлари ва иловалари. Массивлар. Маъруза режаси Хотирани динамик тақсимлаш. С++ да кўрсаткичлари. Адреслар арифметикаси. Массивлар ва кўрсаткичлар орасидаги боғланишлар. Таянч иборалар: Хотирани динамик тақсимлаш, С++ да кўрсаткичлари, кўрсаткичларни аниқлаш, адреслар арифметикаси, массивлар ва кўрсаткичлар орасидаги боғланишлар, new оператори, delete оператори
Хотирани динамик тақсимлаш Локал ўзгарувчилар ва функция параметрлари стекли хотирада жойлаштирилади. Дастур кодлари эса дастур сегментида жойлашади. Глобал ўзгарувчилар хотиранинг глобал ўзгарувчилар соҳасида жойлашади. Регистрли хотира дастурнинг ички хизматчи маълумотларини сақлаш учун хизмат қилади. Хотиранинг қолган қисми эса турли объектлар ўртасида динамик тарзда тақсимланувчи хотира соҳаси, яъни бўш хотирадан иборатдир.
Локал ўзгарувчиларнинг ўзига хос хусусияти шундан иборатки, дастур бошқаруви улар тегишли функциядан чиқиши билан улар локал ўзгарувчилар учун ажратилган хотира соҳаси бўшатилади, яъни бу ўзгарувчиларнинг қийматлари хотирадан ўчирилади. Глобал ўзгарувчилар эса дастур ишга туширилгандан бошлаб токи ўз ишини якунлагунча хотирадан ўчирилмайди, дастурнинг ихтиёрий жойидан уларнинг қийматидан фойдаланишимиз мумкин бўлади. Лекин бу дастур матни тушунарлилигини анча мураккаблаштиради. Локал ва глобал ўзгарувчилар ўзига хос камчиликларга эга. Локал ўзгарувчилардан фақатгина у эълон қилинган функция ишлаб турганда фойдаланиш мумкин бўлса, глобал ўзгарувчилар дастур ишини бошлагандан токи охиригача глобал ўзгарувчилар соҳасидан жой олиб туради. Динамик хотирадан фойдаланиш бу муаммоларни ҳал этади
Динамик хотирани ахборотлар ёзилган ячейкаларнинг номерланган тўплами сифатида қараш мумкин. Стек ўзгарувчиларидан фарқли равишда бу хотира ячейкаларини номлаш мумкин эмас. Уларга мурожаат керакли ячейка адресини ўзида сақлаган кўрсаткичлар орқали амалга оширилади. Маълумки, стек ўзгарувчилари функция ишини тугатиши билан тозаланади. Натижада, барча локал ўзгарувчилар қиймати билан биргаликда хотирадан ўчирилади. Стекдан фарқли равишда динамик хотира дастур ишини тугатгунга қадар бўшатилмайди, бу хотирани бўшатиш билан дастурчиларнинг ўзлари шуғулланишлари лозим.
Динамик хотиранинг яна бир муҳим имконияти шундан иборатки, унинг учун ажратилган хотира соҳаси бўшатилмагунча бу жойдан фойдаланиш мумкин эмас. Яъни, бирор бир қийматни динамик хотирага ёзсак, токи уни у ердан ўчирмагунимизча бу ўзгарувчи учун ажратилган жой бўшатилмайди. Шунинг учун, динамик хотира соҳаси функция билан ишлаш жараёнида ажратилган бўлса, функция ишини тугатгандан кейин ҳам биз ундан бемалол фойдаланишимиз мумкин бўлади. Хотирани динамик тарзда белгилашни глобал ўзгарувчиларни қўллашдан яна бир устунлиги ундаги маълумотларга фақатгина унинг кўрсаткичига мурожаат қилиш имконига эга бўлган функциялар орқалигина мурожаат қилиш мумкин. Кириш имконининг бундай тарзда ташкил этилиши жорий маълумотларни ўзгартирилишини қатъий назорат қилиш имкониятини беради. Бундай услубда ишлаш учун биринчи навбатда динамик хотира соҳаси ячейкаларига кўрсаткич тузиш лозим.
new оператори Хотиранинг объектлар ўртасидан динамик тақсимланувчи соҳасидан жой ажратиш учун new оператори ишлатилади. new операторидан кейин хотирага жойлаштириладиган объект турини кўрсатиш лозим. Бу объектни сақлаш учун талаб этиладиган хотира соҳаси ўлчовини аниқлаш учун керак бўлади. Масалан, new unsigned short int деб ёзиш орқали биз динамик тақсимланувчи хотирадан икки байт жой ажратамиз. Худди шунингдек, new long сатри орқали тўрт байт жой объектлар ўртасида динамик тақсимланувчи соҳадан ажратилади.
new оператори натижа сифатида белгиланган хотира ячейкасининг адресини олади. Бу адрес кўрсаткичга ўзлаштирилиши лозим. Масалан, unsigned short туридаги ўзгарувчи учун динамик соҳадан жой ажратиш учун қуйидаги дастур коди ёзилади: unsigned short int *pPointer; pPointer = new unsigned short int; ёки худди шу амални битта сатрда ҳам ёзиш мумкин: unsigned short int *pPoiner=new unsigned short int;
Иккала ҳолатда ҳам pPointer кўрсаткичи unsigned short int туридаги қийматни сақловчи динамик соҳа хотирасининг ячейкасини кўрсатиб туради. Энда pPointer кўрсаткичи ни шу турдаги ихтиёрий ўзгарувчига кўрсаткич сифатида қўллаш мумкин. Ажратилган хотира соҳасига бирор бир қиймат жойлаштириш учун қуйидагича ёзув ёзилади: *pPointer=72; Бу сатр қуйидаги маънони англатади: « pPointer кўрсаткичида адреси сақланаётган хотирага 72 сонини ёзинг». Динамик хотира соҳаси албатта чегараланган бўлади. У тўлиб қолганда new оператори орқали хотирадан жой ажратишга ўринсак хатолик юз беради. Бу ҳақда кейинроқ тўхталиб ўтамиз.
delete оператори Агарда ўзгарувчи учун ажратилган хотира керак бўлмаса уни бўшатиш зарур. Бу ўзидан кейин кўрсаткич номи ёзиладиган delete оператори ёрдамида амалга оширилади. delete оператори кўрсаткич орқали аниқланган хотира соҳасини бўшатади. Шуни эсда сақлаш лозимки, динамик хотира соҳасидаги адресни ўзида сақловчи кўрсаткич локал ўзгарувчи бўлиши мумкин. Шунинг учун бу кўрсаткич эълон қилинган функциядан чиқишимиз билан кўрсаткич ҳам хотирадан ўчирилади. Лекин new оператори орқали бу кўрсаткичга динамик хотирадан ажратилган жой бўшатилмайди. Натижада хотиранинг бу қисми киришга имконсиз бўлиб қолади. Дастурчилар бу ҳолатни хотиранинг йўқолиши деб тавсифлайдилар. Бу тавсиф ҳақиқатга бутунлай мос келади, чунки дастур ишини якунлагунча хотирани бу қисмидан фойдаланиб бўлмайди.
Хотирани ажратилган қисмини бўшатиш учун delete калитли сўзидан фойдаланилади. Масалан: delete pPointer; Бунда кўрсаткич ўчирилмайди, балки унда сақланаётган адресдаги хотира соҳаси бўшатилади. Белгиланган хотирани бўшатилиши кўрсаткичга таъсир қилмайди, унга бошқа адресни ўзлаштириш ҳам мумкин.
С++ да кўрсаткичлар Кўрсаткич – бу ҳосиловий тур булиб, қандайдир қийматнинг манзилини (адресини) ифодалайди. С++ тилида ўзгарувчиларнинг адреслари тушунчаси ишлатилади. Фараз қилайлик дастурда бутун турдаги ўзгарувчи аниқланган бўлсин: int x; У ҳолда биз х ўзгарувчи қийматига ўзгарувчи кўрсаткични қуйидагича аниқлашимиз мумкин: int* xptr; ва унга xptr га х нинг адресини кийматлашимиз мумкин : xptr = &x; Ўзгарувчига қўлланилган &-операцияси – бу адресни олиш операциясидир. Адресга қўлланилган * операцияси эса, бу адрес бўйича мурожат қилиш операциясидир. Шундай қилиб қуйидаги иккита операциялар эквивалентдир: int y=x; //y ўзгарувчига х қиймат берилади int y=*xptr; //Y ўзгарувчига xptr адресга жойлашган қиймат берилади
Адрес бўйича мурожаат қилиш усули билан маълум бир адресга қиймат бериш мумкин: *xptr=10; // 10 сонини xptr адресга ёзиш Бу оператор бажарилиши билан х ўзгарувчининг қиймати 10 га тенг бўлиб қолади. Кўрсаткич – бу оддий адрес бўлиб қолмасдан, у аниқ бир тур адреси хамдир. Масалан, xptr кўрсаткичи – бутун турдаги катталик адресидир. Бошқа турдаги катталикларнинг адресларини эса шундай аниқлаш мумкин: unsigned long* хрtr;//ишорасиз бутун сонга кўрсаткич char* cp;//байтга кўрсаткичComplex* p; //Complex синфи объектига кўрсаткич Агар кўрсаткич бирон бир синф объектига мурожат қилаётган бўлса, у ҳолда синф атрибутига мурожат қилиш операцияси " -> ", масалан, p->real : void Complex::Add(Complex x){ this->real = this->real + x.real; this- >imaginary = this->imaginary +x.imaginary;} Бу ерда this – бу ерда жорий объектга кўрсаткич ҳисобланади, яъни Add услуб бажараётган объектга. this-> ёзуви жорий объект атрибутига мурожат қилишни билдиради. Исталган турга кўрсаткич аниқлаш мумкин, шу жумладан функцияга ёки усулга хам.
Функцияга кўрсаткич туридаги ўзгарувчини ҳам аниқлаш мумкин, ва бу функцияларни тўғридан-тўғри эмас балки кўрсаткичлар орқали чақириш ҳам мумкин: int (*functptr)(long x);functptr = &foo;(*functptr)(2);functptr = &bar;(*functptr)(4); Кўрсаткичлар асосан системали дарстурлашда ишлатилади, масалан, қурилмалар регистрларига мурожаат қилишда ишлатилади. Бу регистрларнинг ҳаммаси ўз адресларига эгадирлар.