C ++

Як користуватися вказівниками на C ++

Як користуватися вказівниками на C ++
Пам'ять комп'ютера - це довгий ряд комірок. Розмір кожної комірки називається байтом. Байт - це простір, зайнятий англійським символом алфавіту. Об'єкт у звичайному розумінні - це послідовний набір байтів у пам'яті. Кожна клітинка має адресу, яка є цілим числом, зазвичай записаним у шістнадцятковій формі. Існує три способи доступу до об’єкта в пам’яті. Доступ до об’єкта можна отримати за допомогою так званого вказівника. До нього можна отримати доступ, використовуючи те, що відоме як посилання. До нього все ще можна отримати доступ за допомогою ідентифікатора. Ця стаття зосереджена на використанні покажчиків та посилань. У C ++ є вказаний об'єкт та об'єкт-вказівник. Гострий предмет має предмет, що цікавить. Об'єкт вказівника має адресу на вказаний об'єкт.

Ви повинні мати базові знання в C ++, включаючи його ідентифікатори, функції та масиви; щоб зрозуміти цю статтю.

Об’єкт вказівника та загострений об’єкт, кожен має свій ідентифікатор.

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

Це одинарний оператор. Коли слідує ідентифікатор, він повертає адресу об’єкта ідентифікатора. Розглянемо наступну декларацію:

int ptdInt;

Нижче наведено код, наступний вираз поверне адресу, визначену ptdInt:

& ptdInt

Вам не потрібно знати точну адресу (номер) під час кодування.

Непрямий оператор, *

Це одинарний оператор у контексті покажчиків. Зазвичай його набирають перед ідентифікатором. Якщо він використовується в оголошенні ідентифікатора, тоді ідентифікатор - це об'єкт покажчика, який містить лише адресу вказаного об'єкта. Якщо він використовується перед ідентифікатором об'єкта вказівника, щоб щось повернути, тоді повертається річ - це значення вказаного об'єкта.

Створення вказівника

Погляньте на наступний сегмент коду:

float ptdFloat;
float * ptrFloat;
ptrFoat = &ptdFloat;

Сегмент починається з оголошення вказаного об'єкта, ptdFloat. ptdFloat - це ідентифікатор, який просто ідентифікує плаваючий об'єкт. Йому міг бути призначений фактичний об'єкт (значення), але в цьому випадку йому нічого не призначено. Далі в сегменті є оголошення об’єкта вказівника. Оператор опосередкування перед цим ідентифікатором означає, що він повинен утримувати адресу загостреного об'єкта. Тип об’єкта, плаваючий на початку оператора, означає, що загострений об’єкт є плаваючим. Об’єкт вказівника завжди має той самий тип, що і загострений об’єкт. ptrFoat - це ідентифікатор, який просто ідентифікує об'єкт вказівника.

В останньому операторі коду адреса вказаного об'єкта призначається об'єкту покажчика. Зверніть увагу на використання адреси оператора, &.

Останнє твердження (рядок) вище показує, що після оголошення об’єкта вказівника без ініціалізації вам не потрібен оператор опосередкування, коли вам потрібно його ініціалізувати. Насправді використання синтаксичної операції у третьому (останньому) рядку є синтаксичною помилкою.

Об'єкт-вказівник може бути оголошений та ініціалізований вказаним об'єктом в одному операторі, таким чином:

float ptdFloat;
float * ptrFoat = &ptdFloat;

Перший рядок попереднього сегмента коду та цього однаковий. Другий і третій рядки попереднього сегмента коду тут об’єднані в одне твердження.

Зверніть увагу у наведеному вище коді, що при оголошенні та ініціалізації об’єкта вказівника слід використовувати оператор опосередкування. Однак він не використовується, якщо ініціалізацію слід робити пізніше. Об'єкт покажчика ініціалізується адресою вказаного об'єкта.

У наступному сегменті коду оператор опосередкування використовується для повернення вмісту вказаного об'єкта.

int ptdInt = 5;
int * ptrInt = &ptdInt;
кут << *ptrInt << '\n';

Вихід - 5.

В останньому операторі тут оператор опосередкування був використаний для повернення значення, на яке вказує ідентифікатор вказівника. Отже, при використанні в декларації ідентифікатор оператора непрямого використання міститиме адресу вказаного об’єкта. При використанні у виразі повернення у поєднанні з ідентифікатором вказівника оператор непрямого повернення повертає значення вказаного об'єкта.

Присвоєння нулю покажчику

Об'єкт покажчика завжди повинен мати тип загостреного об'єкта. При оголошенні об'єкта вказівника слід використовувати тип даних вказаного об'єкта. Однак значення десяткового нуля можна призначити покажчику, як у наступному сегменті коду:

int ptdInt = 5;
int * ptrInt;
ptrInt = 0;
або в сегменті,
int ptdInt = 5;
int * ptrInt = 0;

У будь-якому випадку покажчик (ідентифікатор) називається нульовим покажчиком; значення, це вказує нікуди. Тобто він не має адреси жодного загостреного об’єкта. Тут 0 - десятковий нуль, а не шістнадцятковий нуль. Шістнадцятковий нуль вказував би на першу адресу пам'яті комп'ютера.

Не намагайтеся отримати значення, на яке вказує нульовий покажчик. Якщо ви спробуєте це, програма може скомпілювати, але не виконати.

Ім'я масиву як постійний вказівник

Розглянемо такий масив:

int arr [] = 000, 100, 200, 300, 400;

Ім'я масиву, arr насправді є ідентифікатором, який має адресу першого елемента масиву. Наступний вираз повертає перше значення в масиві:

* обр

З масивом, оператор збільшення, ++ поводиться по-різному. Замість додавання 1 він замінює адресу вказівника адресою наступного елемента масиву. Однак ім'я масиву є постійним покажчиком; це означає, що його зміст (адресу) не можна змінювати або збільшувати. Отже, для збільшення початкова адреса масиву повинна бути призначена несталому вказівнику наступним чином:

int * ptr = arr;

Тепер ptr можна збільшити, щоб вказати на наступний елемент масиву. ptr оголошено тут як об'єкт покажчика. Без * тут це не був би покажчик; це був би ідентифікатор, який містив би об'єкт int, а не містив адресу пам'яті.

Наступний сегмент коду нарешті вказує на четвертий елемент:

++ptr;
++ptr;
++ptr;

Наступний код виводить четверте значення масиву:

int arr [] = 000, 100, 200, 300, 400;
int * ptr = arr;
++ptr;
++ptr;
++ptr;
кут << *ptr << '\n';

Вихід - 300.

Назва функції як ідентифікатор

Назва функції є ідентифікатором функції. Розглянемо наступне визначення функції:

int fn ()

кут << "seen" << '\n';
повернення 4;

fn - ідентифікатор функції. Вираз,

& fn

повертає адресу функції в пам'яті. fn схожий на загострений предмет. Наступне оголошення оголошує вказівник на функцію:

int (* func) ();

Ідентифікатор загостреного об’єкта та ідентифікатор об’єкта вказівника відрізняються. func - це вказівник на функцію. fn - ідентифікатор функції. Отже, функцію можна зробити так, щоб вказувати на fn наступним чином:

func = &fn;

Значення (вміст) func - це адреса fn. Два ідентифікатори могли бути пов'язані з оператором ініціалізації наступним чином:

int (* func) () = &fn;

Зверніть увагу на відмінності та подібності в роботі з покажчиками функцій та скалярними вказівниками. func - це вказівник на функцію; це загострений предмет; він оголошується інакше, ніж скалярний вказівник.

Функцію можна викликати за допомогою,

fn ()
або
func ()

Його не можна викликати за допомогою * func ().

Коли функція має параметри, другі дужки мають типи параметрів, і їм не потрібно мати ідентифікатори параметрів. Наступна програма це ілюструє:

#включати
використання простору імен std;
float fn (float fl, int in)

повернути fl;

int main ()

float (* func) (float, int) = &fn;
float val = func (2.5, 6);
кут << val << '\n';
повернути 0;

Вихід 2.5.

Посилання на C ++

Посилання на С ++ - це лише спосіб створити синонім (інше ім’я) для ідентифікатора. Він використовує оператор &, але не так, як & використовується для покажчиків. Розглянемо такий сегмент коду:

int myInt = 8;
int & yourInt = myInt;
кут << myInt << '\n';
кут << yourInt << '\n';

Результат:

8
8

Перший оператор ініціалізує ідентифікатор, myInt; i.e. myInt оголошено і зроблено для збереження значення, 8. Друге твердження робить новий ідентифікатор, yourInt синонімом myInt. Для цього оператор & розміщується між типом даних та новим ідентифікатором у декларації. Висловлювання cout показують, що два ідентифікатори є синонімами. Щоб повернути значення в цьому випадку, не потрібно перед ним ставити * . Просто використовуйте ідентифікатор.

myInt і yourInt тут - це не два різні об’єкти. Це два різні ідентифікатори, що посилаються (ідентифікують) одне і те ж місце в пам'яті, що має значення, 8. Якщо значення myInt змінено, значення yourInt також зміниться автоматично. Якщо значення yourInt змінено, значення myInt також зміниться автоматично.

Посилання бувають одного типу.

Посилання на функцію

Подібно до того, як ви можете мати посилання на скаляр, ви можете також мати посилання на функцію. Однак кодування посилання на функцію відрізняється від кодування посилання на скаляр. Наступна програма це ілюструє:

#включати
використання простору імен std;
float fn (float fl, int in)

повернути fl;

int main ()

float (& func) (float, int) = fn;
float val = func (2.5, 6);
кут << val << '\n';
повернути 0;

Вихід 2.5.

Зверніть увагу на перше твердження у головній функції, яке робить func синонімом fn. Обидва посилаються на одну і ту ж функцію. Зверніть увагу на одноразове використання та положення &. Так & є тут оператором посилання, а не адресою оператора. Щоб викликати функцію, просто використовуйте будь-яке ім'я.

Ідентифікатор посилання - це не те саме, що ідентифікатор вказівника.

Функція, що повертає покажчик

У наступній програмі функція повертає покажчик, який є адресою вказаного об'єкта:

#включати
використання простору імен std;
float * fn (float fl, int in)

float * fll = &fl;
return fll;

int main ()

float * val = fn (2.5, 6);
кут << *val << '\n';
повернути 0;

Вихід 2.5

Перший оператор у функції, fn (), призначений лише для створення об'єкта-вказівника. Зверніть увагу на одноразове використання та позицію * у підписі функції. Також зверніть увагу, як вказівник (адреса) був отриманий у функції main () іншим об’єктом вказівника.

Функція, що повертає посилання

У наступній програмі функція повертає посилання:

#включати
використання простору імен std;
float & fn (float fl, int in)

float & frr = fl;
повернути frr;

int main ()

float & val = fn (2.5, 6);
кут << val << '\n';
повернути 0;

Вихід 2.5.

Перший оператор у функції, fn (), призначений лише для створення посилання. Зверніть увагу на одноразове використання та положення & у підписі функції. Також зверніть увагу, як посилання було отримано у функції main () іншим посиланням.

Передача вказівника на функцію

У наступній програмі в якості аргументу функції надсилається покажчик, який насправді є адресою об'єкта з плаваючою стрілкою:

#включати
використання простору імен std;
float fn (float * fl, int in)

повернення * fl;

int main ()

float v = 2.5;
float val = fn (& v, 6);
кут << val << '\n';
повернути 0;

Вихід 2.5

Зверніть увагу на використання та положення * для параметра float у підписі функції. Як тільки починається оцінка функції fn (), робиться таке твердження:

float * fl = & v;

І fl, і & v вказують на один і той же загострений об'єкт, який вміщує 2.5. * fl у операторі повернення не є декларацією; це означає, значення загостреного об'єкта, на який вказує об'єкт вказівника.

Передача посилання на функцію

У наступній програмі посилання надсилається як аргумент функції:

#включати
використання простору імен std;
float fn (float & fl, int in)

повернути fl;

int main ()

float v = 2.5;
float val = fn (v, 6);
кут << val << '\n';
повернути 0;

Вихід 2.5

Зверніть увагу на використання та положення & для параметра float у підписі функції. Як тільки починається оцінка функції fn (), робиться таке твердження:

float & fl = v;

Передача масиву функції

Наступна програма показує, як передати масив функції:

#включати
використання простору імен std;
int fn (int arra [])

return arra [2];

int main ()

int arr [] = 000, 100, 200, 300, 400;
int val = fn (arr);
кут << val << '\n';
повернути 0;

Вихід - 200.

У цій програмі передається масив. Зверніть увагу, що параметр підпису функції має порожнє оголошення масиву. Аргументом у виклику функції є лише ім'я створеного масиву.

Чи може функція C ++ повернути масив?

Функція в C ++ може повернути значення масиву, але не може повернути масив. Компіляція такої програми призводить до повідомлення про помилку:

#включати
використання простору імен std;
int fn (int arra [])

return arra;

int main ()

int arr [] = 000, 100, 200, 300, 400;
int val = fn (arr);
повернути 0;

Покажчик покажчика

Покажчик може вказувати на інший покажчик. Тобто об’єкт покажчика може мати адресу іншого об’єкта покажчика. Вони все одно повинні бути одного типу. Наступний сегмент коду ілюструє це:

int ptdInt = 5;
int * ptrInt = &ptdInt;
int ** ptrptrInt = &ptrInt;
кут << **ptrptrInt << '\n';

Вихід - 5.

У оголошенні покажчика на покажчик використовується подвійний *. Для повернення значення кінцевого загостреного об'єкта все ще використовується double *.

Масив покажчиків

Наступна програма показує, як кодувати масив покажчиків:

#включати
використання простору імен std;
int main ()

int num0 = 000, num1 = 100, num2 = 200, num3 = 300, num4 = 400;
int * no0 = & num0, * no1 = & num1, * no2 = & num2, * no3 = & num3, * no4 =&num4;
int * arr [] = no0, no1, no2, no3, no4;
кут << *arr[4] << '\n';
повернути 0;

Результат:

400

Зверніть увагу на використання та позицію * в оголошенні масиву. Зверніть увагу на використання * при поверненні значення в масиві. З покажчиками покажчиків бере участь два *. У випадку з масивом покажчиків один * вже подбали, оскільки ідентифікатор масиву є покажчиком.

Масив рядків змінної довжини

Рядковий літерал - це константа, яка повертає покажчик. Масив рядків змінної довжини - це масив покажчиків. Кожне значення в масиві є покажчиком. Покажчики - це адреси до місць пам'яті і мають однаковий розмір. Рядки різної довжини знаходяться в інших місцях пам'яті, а не в масиві. Наступна програма ілюструє використання:

#включати
використання простору імен std;
int main ()

const char * arr [] = "жінка", "хлопчик", "дівчинка", "дорослий";
кут << arr[2] << '\n';
повернути 0;

Результат - "дівчина".

Оголошення масиву починається із зарезервованого слова "const" для константи; за яким слідує “char” для символу, потім зірочка, * для позначення того, що кожен елемент є покажчиком. Для повернення рядка з масиву * не використовується через неявний характер вказівника кожного рядка. Якщо використовується *, буде повернено перший елемент рядка.

Покажчик на функцію, що повертає покажчик

Наступна програма ілюструє, як кодується вказівник на функцію, що повертає вказівник:

#включати
використання простору імен std;
int * fn ()

int num = 4;
int * inter = #
return inter;

int main ()

int * (* func) () = &fn;
int val = * func ();
кут << val << '\n';
повернути 0;

Вихід - 4.

Оголошення вказівника на функцію, що повертає вказівник, подібне до оголошення вказівника на звичайну функцію, але перед нею зірочка. Перше твердження у функції main () це ілюструє. Щоб викликати функцію за допомогою вказівника, перед нею ставиться *.

Висновок

Щоб створити вказівник на скаляр, зробіть щось на зразок,

поплавок загострений;
float * покажчик = &pointed;

* має два значення: у декларації це вказівник; щоб щось повернути, це для вартості вказаного об'єкта.

Ім'я масиву є постійним вказівником на перший елемент масиву.

Ви можете створити вказівник на функцію,

int (* func) () = &fn;

де fn () - це функція, визначена в іншому місці, а func - вказівник.

& має два значення: у декларації вказує посилання (синонім) на той самий об’єкт, що і інший ідентифікатор; коли щось повертається, це означає адресу.

Ви можете зробити посилання на функцію,

float (& refFunc) (float, int) = fn;

де fn () - це функція, визначена в іншому місці, а refFunc - посилання.

Коли функція повертає покажчик, повернене значення повинно бути отримане покажчиком. Коли функція повертає посилання, повернене значення має бути отримане посиланням.

При передачі вказівника на функцію параметром є оголошення, тоді як аргументом є адреса вказаного об'єкта. При передачі посилання на функцію параметр є оголошенням, а аргумент - посиланням.

При передачі масиву функції параметр є оголошенням, тоді як аргумент - ім'я масиву без []. Функція C ++ не повертає масив.

Вказівник на покажчик потребує двох * замість одного, де це доречно.

Кріс

How to change Mouse pointer and cursor size, color & scheme on Windows 10
The mouse pointer and cursor in Windows 10 are very important aspects of the operating system. This can be said for other operating systems as well, s...
Безкоштовні ігри з відкритим кодом для розробки ігор Linux
У цій статті буде розглянуто перелік безкоштовних ігрових механізмів з відкритим кодом, які можна використовувати для розробки 2D та 3D ігор на Linux....
Підручник Тінь розкрадача гробниць для Linux
Shadow of the Tomb Raider - дванадцяте доповнення до серії Tomb Raider - франшизи екшн-пригодницької гри, створеної Eidos Montreal. Гру сприйняли як к...