Упражнение 6.2. Укажите, какие из следующих функций ошибочны и почему. Предложите способ их исправления.
(a) int f() {
string s;
// ...
return s;
}
(b) f2(int i) { /* ... */ }
(c) int calc(int v1, int v1) /* ... */ }
(d) double square(double x) return x * x;
Упражнение 6.3. Напишите и проверьте собственную версию функции fact()
.
Упражнение 6.4. Напишите взаимодействующую с пользователем функцию, которая запрашивает число и вычисляет его факториал. Вызовите эту функцию из функции main()
.
Упражнение 6.5. Напишите функцию, возвращающую абсолютное значение ее аргумента.
В языке С++ имя имеет область видимости (см. раздел 2.2.4), а объекты —
• Область видимости имени — это
• Продолжительность существования объекта — это
Как уже упоминалось, тело функции — это блок операторов. Как обычно, блок формирует новую область видимости, в которой можно определять переменные. Параметры и переменные, определенные в теле функции, называются
Объекты, определенные вне любой из функций, существуют на протяжении выполнения программы. Такие объекты создаются при запуске программы и не удаляются до ее завершения. Продолжительность существования локальной переменной зависит от того, как она определена.
Объекты, соответствующие обычным локальным переменным, создаются при достижении процессом выполнения определения переменной в функции. Они удаляются, когда процесс выполнения достигает конца блока, в котором определена переменная. Объекты, существующие только во время выполнения блока, известны как
Параметры — это автоматические объекты. Место для параметров резервируется при запуске функции. Параметры определяются в пределах тела функции. Следовательно, они удаляются по завершении функции.
Автоматические объекты, соответствующие параметрам функции, инициализируются аргументами, переданными функции. Автоматические объекты, соответствующие локальным переменным, инициализируются, если их определение содержит инициализатор. В противном случае они инициализируются значением по умолчанию (см. раздел 2.2.1), а это значит, что значения неинициализированных локальных переменных встроенного типа неопределенны.
Иногда полезно иметь локальную переменную, продолжительность существования которой не прерывается между вызовами функции. Чтобы получить такие объекты, при определении локальной переменной используют ключевое слово static
. Каждый
В качестве простого примера рассмотрим функцию, подсчитывающую количество своих вызовов:
size_t count_calls() {
static size_t ctr = 0; // значение сохраняется между вызовами
return ++ctr;
}
int main() {
for (size_t i = 0; i != 10; ++i)
cout << count_calls() << endl;
return 0;
}
Эта программа выводит числа от 1 до 10 включительно.
Прежде чем процесс выполнения впервые достигнет определения переменной ctr
, она уже будет создана и получит исходное значение 0
. Каждый вызов осуществляет инкремент переменной ctr
и возвращает ее новое значение. При каждом запуске функции count_calls()
переменная ctr
уже существует и имеет некое значение, возможно, оставленное последним вызовом функции. Поэтому при втором вызове значением переменной ctr
будет 1, при третьем — 2 и т.д.
Если у локальной статической переменной нет явного инициализатора, она инициализируется значением по умолчанию (см. раздел 3.3.1), следовательно, локальные статические переменные встроенного типа инициализируются нулем.
Упражнение 6.6. Объясните различия между параметром, локальной переменной и локальной статической переменной. Приведите пример функции, в которой каждая из них могла бы быть полезной.