Прием на B, когато трябва да вземете E. Какво означава в C: какво е указател

24.11.2023

Указателите са изключително мощен инструмент в програмирането. С помощта на указатели някои неща в програмирането могат да бъдат направени много по-лесно и същевременноЕфективността на вашата програма ще се увеличи значително. Указателите дори ви позволяват да обработвате неограничено количество данни.Например, можете да използвате указатели, за да промените стойностите на променливите във функция, като променливите се предават на функцията като параметри. Освен това указателите могат да се използват за динамично разпределяне на памет, което означава, че можете да пишете програми, които могат да обработват практически неограничени количества данни в движение - не е необходимо да знаете, когато пишете програмата колко памет да разпределите предварително. Това е може би най-мощната характеристика на указателите. Първо, нека просто получим общо разбиране за указателите, да се научим как да ги декларираме и използваме.

Какво представляват указателите и защо са необходими?

Указателите са като етикети, които се отнасят до местоположения в паметта. Представете си сейф с различни по размер депозитни кутии в местната банка. Всяка клетка има номер, уникален номер, който е свързан само с тази клетка, така че можете бързо да идентифицирате желаната клетка. Тези числа са подобни на адресите на клетките на компютърната памет. Например, имате богат чичо, който пази всичките си ценности в сейфа си. И за да подсигури всичките си спестявания, той решил да има по-малък сейф, в който да постави карта, която показва местоположението на големия сейф и посочва 16-та парола за големия сейф, в който се съхраняват истинските бижута. По същество сейф с карта ще съхранява местоположението на друг сейф. Цялата тази организация за спестяване на бижута е еквивалентна на указатели в C. В компютъра указателите са просто променливи, които съхраняват адреси на паметта, обикновено адресите на други променливи.

Идеята е, че знаейки адреса на променлива, можете да отидете на този адрес и да получите данните, съхранени в него. Ако трябва да предадете огромна част от данни във функция, много по-лесно е да предадете адреса на паметта, където се съхраняват тези данни, отколкото да копирате всяка част от данните! Освен това, ако програмата се нуждае от повече памет, можете да поискате повече памет от системата. Как действа? Системата просто връща адреса на местоположението в паметта и ние трябва да съхраним този адрес в променлива указател. По този начин можем да взаимодействаме с данни от посоченото място в паметта.

Синтаксис на показалеца

Ако имаме указател, тогава можем да получим неговия адрес в паметта и данните, към които се отнася, поради тази причина указателите имат малко необичаен синтаксис, различен от декларирането на прости променливи. Освен това, тъй като указателите не са обикновени променливи, трябва да кажете на компилатора, че променливата е указател и да му кажете типа данни, към които се отнася указателят. Така че указателят се декларира така:

Data_type *pointerName;

където data_type е типът данни, pointerName е името на указателя.

Например, нека декларираме указател, който съхранява адреса на клетка от паметта, съдържаща цяло число:

Int *integerPointer;

Обърнете внимание на използването на символа * при деклариране на указател. Този символ е ключовият знак в декларацията на указателя. Ако добавите този символ в декларация на променлива, непосредствено преди името на променливата, променливата ще бъде декларирана като указател. Освен това, ако декларирате няколко указателя на един и същи ред, всеки от тях трябва да бъде предшестван от знак звездичка. Нека да разгледаме няколко примера:

// Декларация на указател и проста променлива в един ред int *pointer1, // това е променлива указател; // това е редовна променлива от тип int // Декларация на два указателя в един ред int *pointer1, // това е указател с име pointer1 *pointer2; // това е указател с име pointer2

Както казах, ако името на променливата не е предшествано от символа *, тогава това е обикновена променлива, в противен случай е указател. Точно това показва примерът за декларации на указател по-горе.

Има два начина за използване на показалец:

  1. Използвайте името на показалеца без символа *, по този начин можете да получите действителния адрес на мястото в паметта, към което препраща показалецът.
  2. Използвайте името на показалеца със символа *, за да получите стойността, съхранена в паметта. В контекста на указателите символът * има техническо наименование: операция за дерефериране. По същество ние вземаме препратка към някакъв адрес в паметта, за да получим действителната стойност. Това може да е трудно за разбиране, но в бъдеще ще се опитаме да разберем всичко това.

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

За да декларирате указател, който ще препраща към променлива, първо трябва да получите адреса на тази променлива. За да получите адреса на паметта на променлива (нейното местоположение в паметта), трябва да използвате знака & преди името на променливата. Това ви позволява да разберете адреса на клетката от паметта, в която се съхранява стойността на променливата. Тази операция се нарича операция за вземане на адрес и изглежда така:

Int var = 5; // проста декларация на променлива с предварителна инициализация int *ptrVar; // декларира указател, но той все още не сочи към нищо ptrVar = // сега нашият указател препраща към адреса в паметта, където се съхранява числото 5

IN ред 3беше използвана операцията за вземане на адрес, ние взехме адреса на променливата var и го присвоихме на указателя ptrVar. Нека разгледаме програма, която ясно ще покаже силата на указателите. И така, ето източника:

#включи int main() ( int var; // обикновена целочислена променлива int *ptrVar; // цяло число указател (ptrVar трябва да е от тип int, тъй като ще препраща към тип променлива int) ptrVar = // присвоен на указателя адреса на клетката от паметта, където се намира стойността на променливата var scanf("%d", &var); // променливата var съдържа въведената от клавиатурата стойност printf("%d\n", *ptrVar); // изходна стойност чрез указател getchar(); )

Резултат от програмата:

IN ред 10, printf() отпечатва стойността, съхранена в променливата var. защо се случва това Е, нека да разгледаме кода. IN ред 5, декларирахме променлива var от тип int. IN ред 6— ptrVar указател към целочислена стойност. След това на указателя ptrVar беше присвоен адресът на променливата var, за това използвахме оператора за присвояване на адрес. След това потребителят въвежда число, което се съхранява в променливата var, не забравяйте, че това е същото място, към което ptrVar сочи. Всъщност, тъй като използваме амперсанда, за да присвоим стойност на променливата var във функцията scanf(), трябва да е ясно, че scanf() инициализира променливата var чрез адрес. Указателят ptrVar сочи към същия адрес.

След това, в ред 10, се извършва операцията „дерефериране“ - *ptrVar. Програмата чрез указателя ptrVar чете адреса, който се съхранява в указателя, отива до желаната клетка от паметта на адреса и връща стойността, която се съхранява там.

Имайте предвид, че в примера по-горе, преди указателят да може да се използва, той първо се инициализира, за да се гарантира, че указателят сочи към конкретен адрес в паметта. Ако започнем да използваме указателя, без да го инициализираме, той ще се отнася до всяко място в паметта. А това може да доведе до изключително неприятни последици. Например, операционната система вероятно ще попречи на вашата програма да получи достъп до неизвестно място в паметта, защото операционната система знае, че вашата програма не извършва инициализация на указателя. По принцип това просто причинява срив на програмата.

Ако подобни трикове бяха разрешени в операционната система, можете да получите достъп до всяко място в паметта. И това означава, че за всеки работеща програмаможете да направите свои собствени промени, например, ако имате отворен документ в Word, можете да промените всеки текст програмно. За щастие Windows и други модерни операционни системище ви спре достъпа до тази памет и ще прекрати програмата ви преждевременно.

Ето защо, просто не забравяйте, че за да избегнете срив на вашата програма, винаги трябва да инициализирате указатели, преди да ги използвате.

P.S.: Ако нямате пари на телефона си и няма начин да ги попълните, но спешно трябва да се обадите, винаги можете да използвате доверително плащане на Beeline. Сума доверително плащанеможе да бъде много разнообразна, от 50 до 300 рубли.

Дори ако повечето програмисти разбират разликата между обектите и указателите към тях, понякога не е напълно ясно кой начин за достъп до обект трябва да бъде избран. По-долу сме се опитали да отговорим на този въпрос.

Въпрос

Забелязах, че често програмистите, чийто код видях, използват указатели към обекти по-често, отколкото самите обекти, т.е., например, те използват следната конструкция:

Обект *myObject = нов обект;

Обект myObject;

Същото с методите. Защо вместо това:

MyObject.testFunc();

трябва да напишем това:

MyObject->testFunc();

Доколкото разбирам, това дава печалба в скоростта, защото... имаме директен достъп до паметта. нали P.S. Преминах от Java.

отговор

Обърнете внимание, между другото, че в Java указателите не се използват изрично, т.е. Програмистът не може да получи достъп до обект в код чрез указател към него. В действителност обаче в Java всички типове, с изключение на базовите, са референтни типове: те са достъпни чрез референция, въпреки че е невъзможно изрично да се предаде параметър чрез референция. И също така, забележете, новото в C++ и в Java или C# са напълно различни неща.

За да дадем малка представа какво представляват указателите в C++, ето два подобни кодови фрагмента:

Обект обект1 = нов обект(); // Нов обект Object object2 = new Object(); // Друг нов обект object1 = object2; // И двете променливи се отнасят до обекта, който преди това е бил посочен от object2 // Ако обектът, посочен от object1, се промени, // object2 също ще се промени, защото те са един и същ обект

Най-близкият еквивалент в C++ е:

Обект * обект1 = нов обект(); // Паметта е разпределена за нов обект // Тази памет е посочена от object1 Object * object2 = new Object(); // Същото с втория обект delete object1; // C++ няма система за събиране на боклук, така че ако това не бъде направено, // програмата вече няма да има достъп до тази памет, // поне докато програмата не бъде рестартирана // Това се нарича изтичане на памет object1 = обект2; // Както в Java, object1 сочи към същото място като object2

Това обаче е съвсем различно нещо (C++):

Обект обект1; // Нов обект Object object2; // Друг обект1 = обект2; // Пълното копиране на обект2 в обект1, // вместо предефиниране на указателя, е много скъпа операция

Но ще спечелим ли скорост чрез директен достъп до паметта?

Строго погледнато, този въпрос съчетава два различни въпроса. Първо: кога трябва да използвате динамично разпределение на паметта? Второ: кога трябва да използвате указатели? Естествено, тук не можем без общи думи, че винаги е необходимо да изберете най-подходящия инструмент за работата. Почти винаги има по-добра реализация от използването на ръчно динамично разпределение (динамично разпределение)и/или необработени указатели.

Динамично разпределение

Формулировката на въпроса представя два начина за създаване на обект. И основната разлика е продължителността на живота им (продължителност на съхранение)в програмната памет. Използване на Object myObject; , разчитате на автоматично откриванеживот и обектът ще бъде унищожен веднага след напускане на неговия обхват. Но Object *myObject = нов обект; поддържа обекта жив, докато ръчно не го изтриете от паметта с командата delete. Използвайте последна опциясамо когато наистина е необходимо. И следователно Винагиизберете автоматично определяне на срока на годност на обект, ако е възможно.

Обикновено принудителното определяне на живота се използва в следните ситуации:

  • Необходимо е обектът да съществува дори и след като напусне неговия обхват- точно този обект, точно в тази област на паметта, а не негово копие. Ако това не е важно за вас (в повечето случаи е), разчитайте на автоматичното определяне на живота. Ето обаче пример за ситуация, в която може да се наложи да осъществите достъп до обект извън неговия обхват, но можете да направите това, без изрично да го съхранявате: Като напишете обект във вектор, можете да „прекъснете връзката“ със самия обект - всъщност той (а не негово копие) ще бъде достъпен при извикване от вектор.
  • Трябва да използвате много памет, което може да препълни стека. Страхотно е, ако не се налага да се справяте с такъв проблем (и рядко се сблъсквате с него), защото е „извън компетенциите“ на C++, но за съжаление понякога трябва да решите и този проблем.
  • Например, не знаете точно размера на масива, който ще трябва да използвате. Както знаете, в C++ масивите имат фиксиран размер, когато са дефинирани. Това може да причини проблеми, например при четене на въведеното от потребителя. Указателят дефинира само областта в паметта, където ще бъде записано началото на масива, грубо казано, без да ограничава размера му.

Ако използването на динамично разпределение е необходимо, тогава трябва да го капсулирате с помощта на интелигентен указател (можете да прочетете в нашата статия) или друг тип, който поддържа идиома „Получаването на ресурс се инициализира“ (стандартните контейнери поддържат това - това е идиомът според кой ресурс: блок памет, файл, мрежова връзкаи т.н. - при получаване се инициализира в конструктора и след това внимателно се унищожава от деструктора). Интелигентните указатели са например std::unique_ptr и std::shared_ptr.

Указателни табели

Въпреки това, има случаи, когато използването на указатели е оправдано не само от гледна точка на динамичното разпределение на паметта, но почти винаги има алтернативен начин, без използване на указатели, който трябва да изберете. Както преди, да кажем: винаги избирайте алтернативата, освен ако няма конкретна нужда от използване на указатели.

Случаи, при които използването на указатели може да се разглежда като възможен вариант, можем да назовем следното:

  • Референтна семантика. Понякога може да се наложи достъп до обект (независимо от това как е разпределена паметта за него), защото искате да получите достъп до функции в този обект, а не до неговото копие - т.е. когато трябва да внедрите преминаване по референция. Въпреки това, в повечето случаи тук е достатъчно да използвате връзка, а не указател, защото връзките са създадени за това. Имайте предвид, че това са малко по-различни неща от описаното в точка 1 по-горе. Но ако имате достъп до копие на обекта, тогава няма нужда да използвате препратка (но имайте предвид, че копирането на обект е скъпа операция).
  • Полиморфизъм. Извикването на функции в рамките на полиморфизъм (динамичен обектен клас) е възможно с помощта на препратка или указател. Отново, използването на препратки е за предпочитане.
  • Незадължителен обект. В този случай можете да използвате nullptr, за да посочите, че обектът е пропуснат. Ако това е аргумент на функция, тогава е по-добре да го приложите с аргументи по подразбиране или претоварване. Като алтернатива можете да използвате тип, който капсулира това поведение, като например boost::optional (модифициран в C++14 std::optional).
  • Подобряване на скоростта на компилация. Може да се наложи да отделите компилационни единици (компилационни единици). Една ефективна употреба на указатели е предварителното деклариране (защото, за да използвате обект, първо трябва да го дефинирате). Това ще ви позволи да разпределите единиците за компилиране, което може да има положителен ефект върху ускоряването на времето за компилиране, значително намалявайки времето, изразходвано за този процес.
  • Взаимодействие с библиотекатаC или C-подобен. Тук ще трябва да използвате необработени указатели, освобождавайки памет от тях в последния момент. Можете да получите необработен указател от интелигентен указател, например, с операцията get. Ако библиотеката използва памет, която по-късно трябва да бъде освободена ръчно, можете да рамкирате деструктора в интелигентен указател.

Декларация и инициализация на указателна променлива. Указателите са променливи, чиито стойности са адреси на паметта. Указателят съдържа адреса на променлива, която съдържа конкретна стойност. Променливата се отнася директно към стойност, а указателят индиректно се отнася към стойност. Позоваването на стойност чрез указател се нарича индиректно адресиране.

Указателите, както всички други променливи, трябва да бъдат декларирани, преди да могат да бъдат използвани. В оператора

int *countPtr, count;

декларира се променлива countPtr от тип int* (указател към целочислена стойност). Символът * в декларацията се отнася само за countPtr. Този символ означава, че декларираната променлива е указател. Можете да декларирате указатели, които препращат към обекти от всякакъв тип.

Указателите трябва да бъдат инициализирани или когато са декларирани, или с помощта на оператор за присвояване. Указателят може да бъде инициализиран с нула, NULL макрос или адресна стойност. Указател със стойност NULL не сочи към нищо. Инициализирането на указател със стойност 0 е еквивалентно на инициализирането на указател с константата NULL, но използването на NULL е за предпочитане. Когато се присвои стойност 0, тя се преобразува в указател от съответния тип. Стойността 0 е единственото цяло число, което може да бъде присвоено директно на указателна променлива.

Операции с указатели. Езикът C предлага 5 основни операции, които могат да бъдат приложени към указатели.

    Възлагане. Можете да зададете адрес на указател. Обикновено това действие се извършва с помощта на името на масива или адресния оператор (&).

    Дефиниции на значението. Операторът (*) връща стойността, съхранена в указаната клетка.

    Получаване на адреса на показалеца. Като всяка променлива, променливата указател има адрес и стойност. Операторът & ви казва къде се намира самият показалец.

    Увеличаване на показалеца. Това действие се извършва с помощта на нормалната операция за добавяне или с помощта на операцията за увеличаване. Чрез увеличаване на показалеца, ние го преместваме към следващия елемент от масива.

5. Разлика. Можете да намерите разликата между два указателя. Това обикновено се прави за указатели, които препращат към елементи от същия масив; за да се определи колко далеч са елементите. Резултатът е от същия тип като променливата, съдържаща размера на масива.

Можете да прилагате аритметични операции към указатели, като например: ++, --, +, +=, -, -= и можете да изчислявате разликата на два указателя.

Като пример, нека дефинираме масив int v, чийто първи елемент ще има адрес на паметта, равен на 3000. Инициализираме указателя vPtr със стойността на адрес v, т.е. Стойността на vPtr е 3000 от някой от следните оператори

При добавяне или изваждане на цяло число от указател, неговата стойност се увеличава или намалява не с това число, а с произведението на числото и размера на обекта, към който се отнася указателят.

Размерът на обект в байтове зависи от типа на обекта. Например операторът

ще даде резултат 3008 (3000+2*4), ако 4 байта са разпределени в паметта за цяло число. Сега vPtr ще се отнася до елемент v.

Ако vPtr беше увеличен до стойността 3016, която съответства на адреса на елемента на масива v, тогава изразът

ще върне vPtr на стойност 3000, съответстваща на началото на масива. Когато увеличавате или намалявате указател с единица, можете да използвате операторите за увеличаване (++) и намаляване (--). Всяко от следните твърдения

увеличава стойността на указателя, който ще сочи към следващия елемент от масива. Всеки от следните оператори

Намалява стойността на указателя, който след това получава достъп до предишния елемент от масива.

x = v2Ptr - vPtr;

на променливата x ще бъде присвоен броят елементи на масива, разположени от адреса vPtr до v2Ptr; в този случай това ще бъде стойността 2.

Един указател може да бъде присвоен на друг указател, ако и двата указателя са от един и същи тип. В противен случай трябва да използвате операцията за преобразуване на типа указател от дясната страна на оператора за присвояване към типа указател от лявата страна.

Предаване на параметър по референция. В C указателите и индиректното адресиране се използват за организиране на повикване чрез референция. Ако се извика функция, чиито аргументи трябва да бъдат променени, тогава в този случай към нея се предават адресите на аргументите. Обикновено за тази цел към променливата, чиято стойност ще се промени, се прилага адресната операция (&). Когато адресът на променлива се предава на функция, операторът за индиректно адресиране (*) може да се използва за промяна на нейната стойност. Следната програма показва използването на предаване на параметър чрез препратка.

#включи

( int x=5, y=10;

printf(“x=%d y=%d\n”, x, y);

промяна (&x,&y);

/* предаване на адреси на функции */

printf(“x=%d y=%d\n”, x, y); )

промяна (int *u, int *v)

temp=*u;

Тази функция променя стойностите на променливите x и y. Като предадохме адресите на променливите x и y на функцията, ние й дадохме възможност за достъп до тях. Използвайки указатели и оператора (*), функцията успя да извлече стойностите, поставени в съответните места в паметта, и да ги размени.

Основендалитература: 1 основа, 2 основа

ДопълнителналитератураA: 9 допълнителни

Въпроси за сигурност:

1. Какви са операциите за работа с указатели?

2. С какво число се увеличава стойността на указателя при добавяне на цяло число от указателя?

3. Дайте пример за инициализиране на променлива указател?

4. Дайте пример за деклариране на променлива указател?

5. Каква операция се използва за осъществяване на повикване чрез препратка?

Последна актуализация: 27.05.2017

Указателите в езика C поддържат редица операции: присвояване, получаване на адреса на указател, получаване на стойност от указател, някои аритметични операциии операции за сравнение.

Възлагане

На указател може да бъде присвоен адресът на обект от същия тип, стойността на друг указател или константа NULL.

Задаването на адрес на указател вече беше обсъдено в предишната тема. За да получите адреса на обект, използвайте операцията &:

Int a = 10; int *pa = // указателят pa съхранява адреса на променлива a

Освен това указателят и променливата трябва да имат един и същ тип, в този случай int.

Присвояване на указател към друг указател:

#включи int main(void) ( int a = 10; int b = 2; int *pa = int *pb = printf("Променлива a: адрес=%p \t стойност=%d \n", pa, *pa); printf("Променлива b: адрес=%p \t стойност=%d \n", pb, *pb pa = pb; // сега указателят pa съхранява адреса на променлива b printf("Променлива b: адрес=%p \ t стойност=%d \n", pa, *pa); върне 0; )

Когато указател е присвоен на друг указател, първият указател всъщност започва да сочи към същия адрес, към който сочи вторият указател.

Ако не искаме указателят да сочи към определен адрес, можем да му присвоим условна нулева стойност, използвайки константата NULL, която е дефинирана в заглавния файл stdio.h:

Int *pa = NULL;

Дерефериране на указател

Операцията по дерефериране на указател във формата *име_на_показател ви позволява да получите обект на адреса, който се съхранява в указателя.

#включи int main(void) ( int a = 10; int *pa = int *pb = pa; *pa = 25; printf("Стойност на показалеца pa: %d \n", *pa); // 25 printf(" Стойност на указателя pb: %d \n", *pb); // 25 printf("Стойност на променлива a: %d \n", a); // 25 върне 0; )

Чрез израза *pa можем да получим стойността на адреса, който се съхранява в указателя на pa, а чрез израз като *pa = стойност можем да вмъкнем нова стойност на този адрес.

И тъй като в този случай указателят pa сочи към променливата a, тогава когато стойността на адреса, към който сочи указателят, се промени, стойността на променливата a също ще се промени.

Адрес на показалеца

Указателят съхранява адреса на променлива и от този адрес можем да получим стойността на тази променлива. Но в допълнение, указателят, като всяка променлива, сам по себе си има адрес, на който се намира в паметта. Този адрес може да бъде получен и чрез операцията &:

Int a = 10; int *pa = printf("адрес на показалеца=%p \n", &pa); // адрес на показалеца printf("адрес, съхранен в pointer=%p \n", pa); // адресът, който се съхранява в указателя, е адресът на променливата a printf("стойност на указателя=%d \n", *pa); // стойност на адреса в указателя - стойността на променливата a

Операции за сравнение

Операциите за сравнение > , >= , могат да се прилагат към указатели< , <= ,== , != . Операции сравнения применяются только к указателям одного типа и константе NULL . Для сравнения используются номера адресов:

Int a = 10; int b = 20; int *pa = int *pb = if(pa > pb) printf("pa (%p) е по-голямо от pb (%p) \n", pa, pb); else printf("pa (%p) е по-малко или равно на pb (%p) \n", pa, pb);

Конзолен изход в моя случай:

Pa (0060FEA4) е по-голямо от pb (0060FEA0)

Типово леене

Понякога трябва да присвоите указател от един тип на стойността на указател от друг тип. В този случай трябва да извършите операция за преобразуване на типа:

Char c = "N"; char *pc = int *pd = (int *)pc; printf("pc=%p \n", pc); printf("pd=%p\n", pd);

Указателят е производен тип, който представлява адреса на някаква стойност. Езикът C++ използва концепцията за променливи адреси. Работата с адреси е наследена от C++ от езика C. Да приемем, че в програмата е дефинирана променлива от тип int:

int x;

Можете да дефинирате променлива указател към цяло число:

int* xptr;

и присвоете на променливата xptr адреса на променливата x:

xptr =

Трябва да помним:

  • Операцията &, приложена към променлива, е адресна операция.
  • Операцията *, приложена към адрес (с други думи, приложена към указател), е адресна операция.

Така, за предишните дефиниции на x и y, двата оператора са еквивалентни:

// присвояване на променлива y стойността x

int y = x;

// присвояване на променливата y стойността

// разположен на xptr

int y = *xptr;

Използвайки адресната операция, можете да записвате стойности:

// запишете числото 10 на адрес xptr

*xptr = 10;

След изпълнението на този оператор стойността на променлива x ще бъде 10, защото xptr сочи към променлива x.

Указателят не е просто адрес, а адрес на стойност определен тип. Указателят xptr е адресът на целочислена стойност. Можете да дефинирате адресите на количества от други типове, както следва:

// указател към цяло число без знак

unsigned long* lPtr;

// указател към байт

char* cp;

// указател към обект от класа Complex

Комплекс* p;

Ако указателят препраща към обект от някакъв клас, тогава операцията за достъп до атрибута на класа вместо точка се обозначава с “->”, например p->real. Ако си спомняте един от предишните примери:

void Complex::Add(Complex x)

Това->реално = това->реално + x.real;

Това->въображаемо = това->въображаемо +

X.въображаем;

тогава това е указател към текущия обект, т.е. обект, който изпълнява метода Add. Записът this-> означава достъп до атрибут на текущия обект.

Можете да дефинирате указател към всеки тип, включително функция или метод на клас. Ако има няколко функции от един и същи тип:

int foo(дълъг x);

int bar(дълъг x);

Можете да дефинирате променлива от тип указател към функция и да извикате тези функции не директно, а индиректно, чрез указателя:

int (*functptr)(дълъг x);

функцияptr =

(*funcptr)(2);

функцияptr =

(*funcptr)(4);

За какво са указателите? Указателите се появяват предимно за нуждите на системното програмиране. Тъй като езикът C беше предназначен за програмиране на „ниско ниво“, беше необходимо да се осъществи достъп, например, до регистрите на устройствата. Тези регистри на устройства имат много специфични адреси, т.е. беше необходимо да се прочете или напише стойност на конкретен адрес. Благодарение на механизма на показалеца, такива операции не изискват допълнителни езикови инструменти.

int* hardwareRegiste =0x80000;

*hardwareRegiste =12;

Използването на указатели обаче не се ограничава до нуждите на системното програмиране. Указателите могат значително да опростят и ускорят редица операции. Да предположим, че програмата има област от паметта за съхраняване на междинни резултати от изчисленията. Тази област на паметта се използва от различни програмни модули. Вместо да копираме тази област от паметта всеки път, когато имаме достъп до модула, можем да предадем указател като аргумент на извикването на функцията, като по този начин опростяваме и ускоряваме изчисленията.