Ц ++

Како се користе Ц ++ показивачи

Како се користе Ц ++ показивачи
Меморија рачунара је дугачак низ ћелија. Величина сваке ћелије назива се бајт. Бајт је простор који заузима енглески знак абецеде. Објект у уобичајеном смислу је узастопни скуп бајтова у меморији. Свака ћелија има адресу, која је цео број, обично написана у хексадецималном облику. Постоје три начина за приступ објекту у меморији. Објекту се може приступити помоћу онога што је познато као показивач. Може му се приступити користећи оно што је познато као референца. Још увек му се може приступити помоћу идентификатора. Фокус овог чланка је на употреби показивача и референци. У Ц ++-у постоје шиљати и показивачки објекат. Шиљати предмет има предмет интересовања. Објекат показивача има адресу упереног објекта.

Морате да имате основно знање на језику Ц ++, укључујући његове идентификаторе, функције и низове; да би разумели овај чланак.

Објекат показивача и шиљати објекат имају сваки свој идентификатор.

Адреса оператера, &

Ово је унарни оператер. Када га прати идентификатор, он враћа адресу објекта идентификатора. Узмите у обзир следећу изјаву:

инт птдИнт;

Испод је код, следећи израз ће вратити адресу идентификовану од птдИнт:

& птдИнт

Не морате знати тачну адресу (број) док кодирате.

Индиректни оператер, *

Ово је унарни оператор у контексту показивача. Обично се укуцава испред идентификатора. Ако се користи у декларацији идентификатора, тада је идентификатор објект показивача који садржи само адресу истакнутог објекта. Ако се користи испред идентификатора објекта показивача, да би се нешто вратило, тада је враћена ствар вредност истакнутог објекта.

Креирање показивача

Погледајте следећи сегмент кода:

флоат птдФлоат;
флоат * птрФлоат;
птрФоат = &ptdFloat;

Сегмент започиње декларацијом шиљатог објекта, птдФлоат. птдФлоат је идентификатор, који само идентификује плутајући објекат. Стварни објекат (вредност) му је могао бити додељен, али у овом случају му није додељено ништа. Следеће у сегменту је декларација показивачког објекта. Индиректни оператор испред овог идентификатора значи да мора да држи адресу шиљатог објекта. Тип објекта, флоат на почетку израза, значи да је шиљати објекат флоат. Објекат показивача је увек истог типа као и шиљати објекат. птрФоат је идентификатор, који само идентификује показивачки објекат.

У последњој изјави кода, објекту показивача додељује се адреса истакнутог објекта. Обратите пажњу на употребу адресе оператора, &.

Последња изјава (линија) горе показује да вам након декларисања објекта показивача без иницијализације није потребан индиректни оператор када га морате иницијализовати. У ствари, синтаксна грешка је употреба индиректног оператора у трећем (последњем) реду.

Објект показивача може декларисати и покренути шиљати објекат у једној наредби, како следи:

флоат птдФлоат;
флоат * птрФоат = &ptdFloat;

Прва линија претходног и овог сегмента кода су исте. Други и трећи ред претходног сегмента кода овде су обједињени у једну изјаву.

Имајте на уму у горњем коду да се приликом декларисања и иницијализације показивачког објекта мора користити индиректни оператер. Међутим, не користи се ако ће се иницијализација извршити накнадно. Објекат показивача иницијализује се адресом шиљатог објекта.

У следећем сегменту кода, индиректни оператор се користи за враћање садржаја упереног објекта.

инт птдИнт = 5;
инт * птрИнт = &ptdInt;
цоут << *ptrInt << '\n';

Излаз је 5.

У последњој изјави овде, индиректни оператор је коришћен за враћање вредности на коју је указао идентификатор показивача. Дакле, када се користи у декларацији, идентификатор индиректног оператора би држао адресу истакнутог објекта. Када се користи у повратном изразу, у комбинацији са идентификатором показивача, индиректни оператер враћа вредност истакнутог објекта.

Додељивање нуле показивачу

Објекат показивача увек треба да има тип шиљатог објекта. При декларацији показивачког објекта мора се користити тип података истакнутог објекта. Међутим, вредност децималне нуле може се доделити показивачу као у следећем сегменту кода:

инт птдИнт = 5;
инт * птрИнт;
птрИнт = 0;
или у сегменту,
инт птдИнт = 5;
инт * птрИнт = 0;

У оба случаја, показивач (идентификатор) назива се нулти показивач; значење, упућује нигде. Односно, нема адресу ниједног шиљатог предмета. Овде је 0 децимална нула, а не хексадецимална нула. Хексадецимална нула би указивала на прву адресу меморије рачунара.

Не покушавајте да добијете вредност на коју указује нулти показивач. Ако то покушате, програм се може компајлирати, али се можда неће извршити.

Име низа као константни показивач

Размотрите следећи низ:

инт арр [] = 000, 100, 200, 300, 400;

Име низа, арр је заправо идентификатор који има адресу првог елемента низа. Следећи израз враћа прву вредност у низу:

* арр

Са низом, оператор прираста, ++ се понаша другачије. Уместо да дода 1, он замењује адресу показивача, адресом следећег елемента у низу. Међутим, име низа је стални показивач; што значи да се његов садржај (адреса) не може мењати или увећавати. Дакле, да би се повећао, почетна адреса низа мора бити додељена несталном показивачу на следећи начин:

инт * птр = арр;

Сада се птр може повећати тако да указује на следећи елемент низа. птр је овде декларисан као показивачки објекат. Без * овде, то не би био показивач; то би био идентификатор који садржи инт објекат, а не меморијску адресу.

Следећи сегмент кода коначно упућује на четврти елемент:

++птр;
++птр;
++птр;

Следећи код даје четврту вредност низа:

инт арр [] = 000, 100, 200, 300, 400;
инт * птр = арр;
++птр;
++птр;
++птр;
цоут << *ptr << '\n';

Излаз је 300.

Назив функције као идентификатор

Име функције је идентификатор функције. Размотрите следећу дефиницију функције:

инт фн ()

цоут << "seen" << '\n';
повратак 4;

фн је идентификатор функције. Израз,

& фн

враћа адресу функције у меморији. фн је попут шиљатог предмета. Следећа декларација декларише показивач на функцију:

инт (* фунц) ();

Идентификатор за шиљати објекат и идентификатор за показивачки објекат су различити. фунц је показивач на функцију. фн је идентификатор функције. И тако, фунц може бити постављен тако да указује на фн на следећи начин:

фунц = &fn;

Вредност (садржај) фунц је адреса фн. Два идентификатора су могла бити повезана са наредбом иницијализације на следећи начин:

инт (* фунц) () = &fn;

Обратите пажњу на разлике и сличности у руковању показивачима на функције и скаларним показивачима. фунц је показивач на функцију; то је шиљати предмет; проглашава се другачије од скаларног показивача.

Функција се може позвати помоћу,

фн ()
или
фунц ()

Не може се позвати са * фунц ().

Када функција има параметре, друге заграде имају типове параметара и не морају имати идентификаторе за параметре. Следећи програм то илуструје:

#инцлуде
коришћење простора имена стд;
флоат фн (флоат фл, инт ин)

ретурн фл;

инт маин ()

флоат (* фунц) (флоат, инт) = &fn;
флоат вал = фунц (2.5, 6);
цоут << val << '\n';
ретурн 0;

Излаз је 2.5.

Ц ++ референца

Упућивање на Ц ++ је само начин да се произведе синоним (друго име) за идентификатор. Користи оператор &, али не на исти начин на који се & користи за показиваче. Размотрите следећи сегмент кода:

инт миИнт = 8;
инт & иоурИнт = миИнт;
цоут << myInt << '\n';
цоут << yourInt << '\n';

Излаз је:

8
8

Прва наредба иницијализује идентификатор, миИнт; и.е. миИнт је декларисан и направљен да задржи вредност, 8. Друга изјава чини нови идентификатор, иоурИнт синонимом за миИнт. Да би се то постигло, оператер & се поставља између типа података и новог идентификатора у декларацији. Изјаве цоут-а показују да су два идентификатора синоними. Да бисте вратили вредност у овом случају, не треба да јој претходете * . Само користите идентификатор.

миИнт и иоурИнт овде нису два различита објекта. То су два различита идентификатора који упућују (идентификују) исту локацију у меморији која има вредност, 8. Ако се вредност миИнт промени, вредност иоурИнт ће се такође аутоматски променити. Ако се вредност иоурИнт промени, вредност миИнт ће се такође аутоматски променити.

Референце су истог типа.

Упућивање на функцију

Као што можете имати референцу на скалара, тако можете имати референцу на функцију. Међутим, кодирање референце на функцију разликује се од кодирања референце на скалар. Следећи програм то илуструје:

#инцлуде
коришћење простора имена стд;
флоат фн (флоат фл, инт ин)

ретурн фл;

инт маин ()

флоат (& фунц) (флоат, инт) = фн;
флоат вал = фунц (2.5, 6);
цоут << val << '\n';
ретурн 0;

Излаз је 2.5.

Обратите пажњу на прву изјаву у главној функцији, која чини фунц синонимом фн. Обоје упућују на исту функцију. Обратите пажњу на једнократну употребу и положај &. Дакле, & је овде референтни оператор, а не адреса адресе. Да бисте позвали функцију, само користите било које име.

Референтни идентификатор није исто што и идентификатор показивача.

Функција која враћа показивач

У следећем програму функција враћа показивач који је адреса истакнутог објекта:

#инцлуде
коришћење простора имена стд;
флоат * фн (флоат фл, инт ин)

флоат * флл = &fl;
ретурн флл;

инт маин ()

флоат * вал = фн (2.5, 6);
цоут << *val << '\n';
ретурн 0;

Излаз је 2.5

Прва изјава у функцији, фн () постоји само да би креирала показивачки објекат. Обратите пажњу на једнократну употребу и положај * у потпису функције. Такође имајте на уму како је показивач (адреса) у функцији маин () примљен од другог објекта показивача.

Функција која враћа референцу

У следећем програму функција враћа референцу:

#инцлуде
коришћење простора имена стд;
флоат & фн (флоат фл, инт ин)

флоат & фрр = фл;
ретурн фрр;

инт маин ()

флоат & вал = фн (2.5, 6);
цоут << val << '\n';
ретурн 0;

Излаз је 2.5.

Прва изјава у функцији, фн () постоји само да би креирала референцу. Обратите пажњу на једнократну употребу и положај & у потпису функције. Такође имајте на уму како је референца у функцији маин () примљена од стране друге референце.

Прослеђивање показивача на функцију

У следећем програму, показивач, који је уствари адреса плутајућег објекта, шаље се као аргумент функцији:

#инцлуде
коришћење простора имена стд;
флоат фн (флоат * фл, инт ин)

ретурн * фл;

инт маин ()

флоат в = 2.5;
флоат вал = фн (& в, 6);
цоут << val << '\n';
ретурн 0;

Излаз је 2.5

Обратите пажњу на употребу и положај * параметра флоат у потпису функције. Чим започне процена функције фн (), даје се следећа изјава:

флоат * фл = & в;

И фл и & в показују на исти шиљати објекат који држи 2.5. * фл у повратној изјави није изјава; то значи, вредност шиљатог објекта на који указује показивачки објекат.

Прослеђивање референце на функцију

У следећем програму референца се шаље као аргумент функцији:

#инцлуде
коришћење простора имена стд;
флоат фн (флоат & фл, инт ин)

ретурн фл;

инт маин ()

флоат в = 2.5;
флоат вал = фн (в, 6);
цоут << val << '\n';
ретурн 0;

Излаз је 2.5

Обратите пажњу на употребу и положај & за параметар флоат у потпису функције. Чим започне процена функције фн (), даје се следећа изјава:

флоат & фл = в;

Прослеђивање низа функцији

Следећи програм показује како пренети низ функцији:

#инцлуде
коришћење простора имена стд;
инт фн (инт арра [])

ретурн арра [2];

инт маин ()

инт арр [] = 000, 100, 200, 300, 400;
инт вал = фн (арр);
цоут << val << '\n';
ретурн 0;

Излаз је 200.

У овом програму се предаје низ. Имајте на уму да параметар потписа функције има празну декларацију низа. Аргумент у позиву функције само је име креираног низа.

Може ли функција Ц ++ да врати низ?

Функција у Ц ++ може да врати вредност низа, али не може да врати низ. Састављање следећег програма доводи до поруке о грешци:

#инцлуде
коришћење простора имена стд;
инт фн (инт арра [])

ретурн арра;

инт маин ()

инт арр [] = 000, 100, 200, 300, 400;
инт вал = фн (арр);
ретурн 0;

Показивач показивача

Показивач може усмерити на други показивач. Односно, показивачки објект може имати адресу другог показивачког објекта. Још увек морају бити истог типа. Следећи сегмент кода то илуструје:

инт птдИнт = 5;
инт * птрИнт = &ptdInt;
инт ** птрптрИнт = &ptrInt;
цоут << **ptrptrInt << '\n';

Излаз је 5.

У декларацији показивача на показивач користи се доубле *. Да би се вратила вредност коначног шиљатог објекта, и даље се користи доубле *.

Низ показивача

Следећи програм показује како кодирати низ показивача:

#инцлуде
коришћење простора имена стд;
инт маин ()

инт нум0 = 000, нум1 = 100, нум2 = 200, нум3 = 300, нум4 = 400;
инт * но0 = & нум0, * но1 = & нум1, * но2 = & нум2, * но3 = & нум3, * но4 =&num4;
инт * арр [] = бр0, бр1, бр2, бр3, бр4;
цоут << *arr[4] << '\n';
ретурн 0;

Излаз је:

400

Обратите пажњу на употребу и положај * у декларацији низа. Обратите пажњу на употребу * када враћате вредност у низу. Са показивачима показивача, два * су укључена. У случају низа показивача, један * је већ збринут, јер је идентификатор низа показивач.

Низ жица променљиве дужине

Знаковни низ је константа која враћа показивач. Низ знаковних низова променљиве дужине је низ показивача. Свака вредност у низу је показивач. Показивачи су адресе меморијских локација и исте су величине. Низови различитих дужина налазе се негде другде у меморији, а не у низу. Следећи програм илуструје употребу:

#инцлуде
коришћење простора имена стд;
инт маин ()

цонст цхар * арр [] = "жена", "дечак", "девојчица", "одрасла особа";
цоут << arr[2] << '\n';
ретурн 0;

Резултат је „девојчица“.

Декларација низа започиње резервисаном речју, „цонст“ за константу; након чега следи знак „цхар“ за знак, затим звездица, * да означи да је сваки елемент показивач. Да би се низ вратио из низа, * се не користи због имплицитне природе показивача сваког низа. Ако се користи *, вратит ће се први елемент низа.

Показивач на функцију која враћа показивач

Следећи програм илуструје како је кодиран показивач на функцију која враћа показивач:

#инцлуде
коришћење простора имена стд;
инт * фн ()

инт нум = 4;
инт * интер = #
ретурн интер;

инт маин ()

инт * (* фунц) () = &fn;
инт вал = * фунц ();
цоут << val << '\n';
ретурн 0;

Излаз је 4.

Декларација показивача на функцију која враћа показивач слична је декларацији показивача на уобичајену функцију, али јој претходи звездица. Прва изјава у функцији маин () то илуструје. Да бисте позвали функцију помоћу показивача, ставите је испред *.

Закључак

Да бисте креирали показивач на скалар, учините нешто слично,

пловак зашиљен;
флоат * показивач = &pointed;

* има два значења: у декларацији означава показивач; вратити нешто, то је за вредност шиљатог предмета.

Име низа је стални показивач на први елемент низа.

Можете да направите показивач на функцију,

инт (* фунц) () = &fn;

где је фн () функција дефинисана на другом месту, а функц је показивач.

& има два значења: у декларацији означава референцу (синоним) на исти објекат као други идентификатор; када нешто враћате, то значи адресу.

Можете створити референцу на функцију,

флоат (& рефФунц) (флоат, инт) = фн;

где је фн () функција дефинисана на другом месту, а рефФунц је референца.

Када функција враћа показивач, враћену вриједност мора примити показивач. Када функција враћа референцу, враћена вредност мора да буде примљена референцом.

Приликом просљеђивања показивача на функцију, параметар је декларација, док је аргумент адреса усмјереног објекта. Приликом просљеђивања референце на функцију, параметар је декларација, док је аргумент референца.

Приликом просљеђивања низа функцији, параметар је декларација, док је аргумент име низа без []. Функција Ц ++ не враћа низ.

Поинтер за показивач треба два * уместо једног, где је то потребно.

Цхрис

Како преузети и играти Сид Меиер'с Цивилизатион ВИ на Линук-у
Увод у игру Цивилизатион 6 је модерни поглед на класични концепт представљен у серији игара Аге оф Емпирес. Идеја је била прилично једноставна; започе...
Како инсталирати и играти Доом на Линук-у
Увод у Доом Доом серија настала је 90-их година након објављивања оригиналног Доом-а. То је био тренутни хит и од тог времена надаље серија игара је д...
Вулкан за кориснике Линука
Са сваком новом генерацијом графичких картица видимо да програмери игара помичу границе графичке верности и долазе на корак од фотореализма. Али упрко...