■ Они занимают память в течение всего времени выполнения программы, а не только тогда, когда действительно необходимы.
■ Использование глобальной переменной в "роли", с которой легко бы "справилась" локальная переменная, делает такую функцию менее универсальной, поскольку она полагается на необходимость определения данных вне этой функции.
■ Использование большого количества глобальных переменных может привести к появлению ошибок в работе программы, поскольку при этом возможно проявление неизвестных и нежелательных побочных эффектов. Основная проблема, характерная для разработки больших С++-программ, — случайная модификация значения переменной в каком-то другом месте программы. Чем больше глобальных переменных в программе, тем больше вероятность ошибки.
До сих пор в приводимых здесь примерах функциям передавались значения простых переменных. Но возможны ситуации, когда в качестве аргументов необходимо использовать указатели и массивы. Рассмотрению особенностей передачи аргументов этого типа и посвящены следующие подразделы.
В C++ разрешается передавать функции указатели. Для этого достаточно объявить параметр типа указатель. Рассмотрим пример.
// Передача функции указателя.
#include <iostream>
using namespace std;
void f (int *j);
int main()
{
int i;
int *p;
p = &i; // Указатель p теперь содержит адрес переменной i.
f(p);
cout << i; // Переменная i теперь содержит число 100.
return 0;
}
void f (int *j)
{
*j = 100; // Переменной, адресуемой указателем j, присваивается число 100.
}
Как видите, в этой программе функция f() принимает один параметр: указатель на целочисленное значение. В функции main() указателю р присваивается адрес переменной i. Затем из функции main() вызывается функция f(), а указатель р передается ей в качестве аргумента. После того как параметр-указатель j получит значение аргумента р, он (так же, как и р) будет указывать на переменную i, определенную в функции main(). Таким образом, при выполнении операции присваивания
*j = 100;
переменная i получает значение 100. Поэтому программа отобразит на экране число 100. В общем случае приведенная здесь функция f() присваивает число 100 переменной, адрес которой был передан этой функции в качестве аргумента.
В предыдущем примере необязательно было использовать переменную р. Вместо нее при вызове функции f() достаточно использовать переменную i, предварив ее оператором "&" (при этом, как вы знаете, генерируется адрес переменной i). После внесения оговоренного изменения предыдущая программа приобретает такой вид.
// Передача указателя функции -- исправленная версия.
#include <iostream>
using namespace std;
void f (int *j);
int main()
{
int i;
f(&i);
cout << i;
return 0;
}
void f (int * j)
{
*j = 100; // Переменной, адресуемой указателем j, присваивается число 100.
}
Передавая указатель функции, необходимо понимать следующее. При выполнении некоторой операции в функции, которая использует указатель, эта операция фактически выполняется над переменной, адресуемой этим указателем. Таким образом, такая функция может изменить значение объекта, адресуемого ее параметром.
Если массив является аргументом функции, то необходимо понимать, что при вызове такой функции ей передается только адрес первого элемента массива, а не полная его копия. (Помните, что в C++ имя массива без индекса представляет собой указатель на первый элемент этого массива.) Это означает, что объявление параметра должно иметь тип, совместимый с типом аргумента. Вообще существует три способа объявить параметр, который принимает указатель на массив. Во-первых, параметр можно объявить как массив, тип и размер которого совпадает с типом и размером массива, используемого при вызове функции. Этот вариант объявления параметра-массива продемонстрирован в следующем примере.