Студопедия.Орг Главная | Случайная страница | Контакты | Мы поможем в написании вашей работы!  
 

Посилання



Посилання (reference) – особливий тип даних, що є прихованою формою вказівника, який при зверненні автоматично розіменовується. Посилання можна розглядати як ще одне ім'я об'єкту.

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

type &reference_name

позначає оголошення посилання на об'єкт типу type.

Наприклад:

int i = 1;

int &r = i; // r та i посилаються на одне і те ж ціле

int x = r; // x = 1

r = 2; // i = 2;

Посилання обов'язково має бути ініціалізоване, тобто повинно бути щось, ім'ям чого воно є. Ініціалізація посилання – це у жодному випадку не операція присвоювання.

Ніякі операції над посиланнями не виконуються. Наприклад:

int ii = 0;

int &rr = ii;

rr++; // ii збільшується на 1

int *pp = &rr; // pp вказує на ii

Графічно зв'язки між змінною ii, посиланням rr та вказівником pp представлені на мал. 2.1.

Малюнок 2.1 Зв'язки між змінною, посиланням та вказівником

Операція ++ над посиланням допустима, але вираз rr++ не збільшує саме посилання rr; натомість операція ++ застосовується до цілого, тобто до змінної ii. Отже, після ініціалізації значення посилання не може бути змінено: воно завжди вказує на той об'єкт, до якого було прив'язане при його ініціалізації.

Щоб одержати адресу об'єкту, який позначений посиланням rr, треба написати &rr.

Масиви

Для заданого типу type оголошення:

type array_name[size];

формує в пам'яті масив з size елементів типу type. Елементи індексуються від 0 до size-1. Наприклад:

float v[3]; // масив з трьох чисел з плаваючою крапкою:

// v[0], v[1], v[2]

int а[2][5]; // два масиви, з п'яти цілих кожен

char* vpc[31]; // масив з 32–х вказівників на символи

// vpc[0], vpc[1], …, vpc[31]

Для звернення до значення елементу масиву задається ім'я масиву і індекс елементу масиву index в квадратних дужках:

array_name[index]

Можна таким чином записати цикл, в якому друкуються цілі значення малих літер:

extern "C" int strlen(const char*); // з <string.h>

char alpha[] = "abcdefghijklmnopqrstuvwxyz";

main()

{

int sz = strlen(alpha);

for (int i = 0; i<sz; i++)

{

char ch = alpha[i];

cout << '\''<< ch << '\''

<< " = " << int(ch)

<< " = 0" << oct(ch)

<< " = 0x" << hex(ch)<< '\n';

}

}

Тут функції oct() і hex() повертають значення свого аргументу цілого типу у вісімковому і шіснадцятковому зображенні, відповідно. Обидві функції описані в бібліотечному файлі <iostream>. Для підрахунку числа символів в alpha використовується функціяstrlen() з бібліотечного файлу <string>; але замість неї можна було б використати розмір масиву alpha. Результат роботи програми буде таким:

'a' = 97 = 0141 = 0x61

'b' = 98 = 0142 = 0x62

'c' = 99 = 0143 = 0x63

...

Відзначимо, що не потрібно вказувати розмір масиву alpha: компілятор встановить його, підрахувавши число символів в рядку, заданому як ініціалізатор. Початкове задавання масиву символів у вигляді рядка ініціалізатора - це зручний, але, на жаль, єдиний спосіб подібного застосування рядків. Присвоювання рядка масиву неприпустимо, оскільки в мові присвоювання масивам не визначено, наприклад:

char v[9];

v = "а string"; // помилка

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

int v[5][2]; // правильно

int badv[4, 1]; // помилка

2.4.1 Ініціалізація масивів

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

int v1[4] = {1, 2, 3, 4};

int v2[4] = {'a', 'b', 'c', 'd'};

Коли масив оголошений без зазначення розміру, але при цьому ініціалізується списком, розмір масиву визначається шляхом підрахунку числа елементів цього списку. Наприклад:

char v3[] = {1, 2, 3, 4};

char v4[] = {'a', 'b', 'c', 'd'};

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

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

char v[2][5]= {

{'a', 'b', 'c', 'd', 'e'}

{'0', '1', '2', '3', '4'}

};

Цей масив може бути використаний таким чином:

main()

{

for (int i = 0; i<2; i++)

{

for (int j = 0; j<5; j++)

cout << "v[" << i << "][" << j

<< "] =" << v[i][j] << " ";

cout << '\n';

}

}

В результаті роботи програми одержимо на екрані:

v[0][0]=a v[0][1]=b v[0][2]=c v[0][3]=d v[0][4]=e

v[1][0]=0 v[1][1]=1 v[1][2]=2 v[1][3]=3 v[1][4]=4

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

int v5[8]= {1, 2, 3, 4};

рівнозначно

int v5[8]= {1, 2, 3, 4, 0, 0, 0, 0};

2.4.2 Вказівники й масиви

Вказівники й масиви в мові C++ тісно зв'язані. Ім'я масиву можна використовувати як вказівник на його перший елемент. Наприклад:

int v[] = {1, 2, 3, 4};

int p1 = v; // вказівник на перший елемент масиву

int p2 = &v[0]; // також вказівник на перший елемент масиву

int p3 = &v[4]; // вказівник на елемент, наступний за останнім

// елементом масиву

Графічно цей приклад відображений на мал. 2.2.

 
 

Малюнок 2.2 Зв'язок між масивом і вказівниками

У мові гарантується осмисленість значення вказівника на елемент, наступний за останнім елементом масиву.

Приклад програми роботи з масивом alpha з застосуванням вказівника можна переписати так:

int main()

{

char alpha[] = "abcdefghijklmnopqrstuvwxyz";

char *p = alpha;

char ch;

while (ch = *p++)

cout << '\''<< ch << '\''

<< " = " << int(ch)

<< " = 0" << oct(ch)

<< " = 0x" << hex(ch)<< '\n';

}

Можна також оголосити p таким чином:

char *p = &alpha[0];

Ця еквівалентність широко використовується при викликах функцій з аргументом-масивом, який завжди передається як вказівник на його перший елемент. Таким чином, в наступному прикладі в обох викликах strlen() передається одне і те ж значення:

void f()

{

extern "C" int strlen(const char*); // з файлу <string.h>

char v[] = "Annemarie";

char *p = v;

strlen(p);

strlen(v);

}

2.4.3 Доступ до елементів масиву

Доступ до елементів масиву може проводитися або за допомогою вказівника на масив та індексу елементу, або через вказівник на елемент масиву. Розглянемо приклад функції обчислення суми елементів масиву з використанням індексу для перебору елементів масиву:

int fi(int v[], int N)

{

int sum = 0;

for (int i = 0; i < N; i++) sum += v[i];

return sum;

}

Це рівнозначно наступному прикладу, в якому для проходу по масиву використовується вказівник:

int fp(int v[], int N)

{

int sum = 0;

int *pN = v + N;

for (int *p = v; p!= pN; i++)

sum += v[*p];

return sum;

}

Як вже мовилося раніше, префіксний оператор * означає розіменування, тому *p є значенням елементу масиву, на який вказує р.

Результат застосування до вказівників арифметичних операцій +, -, ++ або -- залежить від типу вказуваних об'єктів. Якщо така операція застосовується до вказівника p типу T*, то вважається, що p указує на масив об'єктів типу T. Тоді p+1 позначає наступний елемент цього масиву, а p-1 - попередній елемент. Звідси витікає, що значення p+1 буде на sizeof(T) байтів більше, ніж значення р.

Віднімання вказівників визначено тільки в тому випадку, коли вони обидва вказують на один і той же масив (хоча в мові немає можливостей гарантувати цей факт). Результат віднімання одного вказівника від іншого рівний числу елементів масиву, що знаходяться між цими вказівниками. Можна складати з вказівником або віднімати з нього значення цілого; в обох випадках результатом буде вказівник.

Як правило, складних арифметичних операцій з вказівниками виконувати не потрібно і краще всього їх уникати.

Слід сказати, що при роботі з масивами як з використанням індексів, так і при роботі через вказівники, компілятори мови С++ не забезпечують контроль над межами масивів.





Дата публикования: 2014-11-03; Прочитано: 676 | Нарушение авторского права страницы | Мы поможем в написании вашей работы!



studopedia.org - Студопедия.Орг - 2014-2024 год. Студопедия не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования (0.011 с)...