Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
38
Добавлен:
16.04.2013
Размер:
76.8 Кб
Скачать

Передача массивов функциям

В определении функции формальный параметр, который объявлен как массив, по сути является указателем. Когда функции передается массив, на самом деле передается по значению его базовый адрес. Сами элементы массива не копируются. Для удобства записи компилятор допускает запись с квадратными скобками [ ] (как у массивов) при объявлении указателей в качестве параметров.

int sum (const int a [ ], int n) // n – это размер массива a [ ]

{

int i, s = 0;

for (i = 0; i <n; ++i)

s +=a [i];

return s;

}

Как часть заголовка определения функции объявление

int a [ ]; равнозначно int *a;

Вызов

Результат

sum ( v, 100 )

v[0] + v[1] + …+ v[99]

sum ( v, 88 )

v[0] + v[1] + …+ v[87]

sum ( v + 7, k )

v[7] + v[8] + …+ v[k+6]

Объявления ссылок и вызовов по ссылке

Объявление ссылки вводит идентификатор, который будет альтернативным именем или псевдонимом (alias), для объекта, указанного при инициализации ссылки, и допускает более простую форму параметров при вызове по ссылке. Например:

int n;

int& nn = n; // nn - альтернативное имя для n

double a [10];

double& last = a[9]; // last - псевдоним для a[9]

Объявление ссылки, которое является ее определением, должно содержать инициализатор. Обычно ссылки инициализируются простыми переменными. В примерах выше имена n и nn – псевдонимы друг для друга, то есть они ссылаются на один и тот же объект. Изменение nn равнозначно изменению n и наоборот. Имя last является альтернативным именем для конкретного элемента массива a[9]. Будучи однажды инициализованы, эти имена не могут быть изменены.

Предположим, что память по адресу 1004 используется для хранения целой переменной a, а память по адресу 1008 – для переменной - указателя p.

int a = 5; // объявление a

int* p = &a; // p указывает на a

int& ref_a = a; // псевдоним для a

*p = 7; // выражению lvalue присваивается 7

a = *p + 1; // к rvalue 7 добавляется 1 и a

// присваивается 8

p адрес 1008

1004

5 7 8

адрес 1004

а

ref_a является псевдонимом для a

Обратите внимание, что любое изменение значения a равносильно изменению ref_a.

Рассмотрим функцию order ( ).

void order (int& p, int& q)

{

int temp;

if (p > q) {

temp = p;

p = q;

q = temp;

}

}

Прототип и вызов из main ( ) функции order ( ) может выглядеть так:

void order (int& , int& );

int main ( )

{

int i, j;

…..

order (i, j);

…..

}

При вызове order (i, j), если их значения i > j изменяются. Если бы вызвать без ссылок, их значения не изменились.

В C++ оператор new принимает следующие формы:

new имя_типа

new имя_типа инициализатор

new имя_типа [выражение]

В каждом случке имеется по крайней мере два эффекта. Во-первых, выделяется надлежащий объем свободной памяти для хранения указанного типа. Во-вторых, возвращается базовый адрес объекта (в качестве значения оператора new). Когда память недоступна, оператор new либо возвращает значение 0 либо возбуждает соответствующее исключение (см. раздел 11.10, «Стандартные исключения и их использование», на стр. 324).

В следующем примере используется оператор new:

int *p, *q;

p = new int (5); // выделение памяти и инициализация

q = new int [10]; // получаем массив от q [0] до q [9]причем q = &q[0]

В этом фрагменте указателю на целое p присваивается адрес ячейки памяти, полученный при размещении целого объекта. Место в памяти, на которое указывает p, инициализуется значением 5.

Оператор delete уничтожает объект, созданный с помощью new, отдавая тем самым распределенную память для повторного использования. Оператор delete может принимать следующие формы:

delete выражение

delete[ ] выражение

Первая форма используется, если соответствующее выражение new размещало не массив. Во второй форме присутствуют пустые квадратные скобки, показывающие, что изначально размещался массив объектов. Оператор delete не возвращает значения, поэтому можно сказать, что возвращаемый им тип – void.

В следующем примере эти конструкции используются для динамического распределения памяти.

double avg_arr (const int a [ ], int size)

{

int sum = 0;

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

sum += a [i];

return static_cast<double> (sum) / size;

}

int main ( )

{

int* data;

int size;

for (int n_loop = 0; n_loop < 5; ++n_loop) {

cout << “ \ n Введите размер массива: ” ;

cin >> size;

assert (size > 0); //если size  0, аварийное завершение

data = new int [size]; //размещение массива

assert (data != 0); //если data == 0, аварийное завершение

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

cin >> data [j];

cout << “ среднее равно ”

<< avg_arr (data, ssize) << endl;

delete [ ] data; //освобождение памяти, занимаемой массивом

}

}

Наше вводное обсуждение операторов свободной памяти относится к простым случаям. Возможна перегрузка операторов new и delete.

Соседние файлы в папке Тельминов (мб)