БЕСПЛАТНАЯ ПОДГОТОВКА К ЕГЭ ПО ПРОФИЛЬНОЙ МАТЕМАТИКЕ
Подготовься к ЕГЭ-2026 по профильной математике самостоятельно с помощью сервиса "1С:Репетитор"!
Понятная теория и эффективные тренажеры с объяснением! Вы успеете подготовиться к экзамену! Начните занятия прямо сейчас!
design_arrow
Передача аргументов в функцию

Передача аргументов в функцию

Передача аргументов в функцию – фундаментальный механизм абстракции и повторного использования кода. От выбранной модели передачи (по значению, по ссылке, по указателю, копирование-вход/копирование-выход, по имени, по «совместному использованию объекта») зависят корректность алгоритма, вычислительные затраты, предсказуемость побочных эффектов и доказуемость инвариантов. В работе формализованы базовые понятия (формальные/фактические параметры, область видимости, время жизни, активационная запись), разобраны семантики и их связь с мутабельностью данных, даны строгие правила проектирования и типовые идиомы, показаны риски алиасинга и ловушки значений по умолчанию. Показано, как эти знания применяются в задачах ЕГЭ: трассировка, вычисление результатов, работа с массивами/строками/записями, оценка стоимости копирования и преобразование решений между разными семантиками. Завершает материал практикум из пяти упражнений формата ЕГЭ.

Понятийный аппарат

  • Функция (процедура) – именованный фрагмент программы, принимающий формальные параметры и (в случае функции) возвращающий значение.

  • Фактические параметры (аргументы вызова) – выражения, переданные при вызове.

  • Связывание (binding) – сопоставление фактических параметров формальным: по позиции и/или по имени (ключевые аргументы).

  • Активационная запись (кадр стека) – структура, создаваемая при вызове: хранит формальные параметры, локальные переменные, адрес возврата, сохранённые регистры и т. п.

  • Область видимости – множество участков кода, где имя параметра доступно (обычно статическая/лексическая).

  • Время жизни – интервал, когда объект существует в памяти (локальные – до возврата; динамические – до явного освобождения/сборки мусора).

  • Ключевая идея. Передача – это не «копировать или не копировать» в отрыве от контекста. Важны (а) семантика языка, (б) тип и мутабельность объекта, (в) договорённость о направлении передачи: in (только чтение), out (только запись), inout (чтение+запись).

Модели передачи параметров

  1. По значению (call by value)

    Фактическое выражение вычисляется, результат копируется в формальный параметр. Изменения формального параметра не влияют на аргумент вызова.

    • Плюсы: изоляция, предсказуемость, простое доказательство корректности.

    • Минусы: стоимость копирования; не подходит для намеренной модификации входа.

    • Стоимость: Θ(размера данных) (скаляры – O(1), большие структуры – O(n)).

  2. По ссылке (call by reference)

    Формальный параметр становится синонимом (алиасом) аргумента. Изменения видны вызывающей стороне.

    • Плюсы: отсутствие копирования; возможность out/inout.

    • Минусы: риск неочевидных побочных эффектов, сложнее инварианты; опасность «висячих» ссылок при выходе.

    • Требование: задавайте контракт (пред-/постусловия), отмечайте «только чтение» (константная ссылка) при отсутствии намерения модификации.

  3. По указателю (pointer semantics)

    Передаётся значение указателя (адрес). Семантически близко к передаче по значению указателя, что даёт опосредованный доступ к объекту.

    • Плюсы: явная управляемость адресами, совместима с «нет ссылок в языке».

    • Минусы: нулевые/невалидные указатели, двойные разыменования, необходимость дисциплины владения.

  4. Копирование-вход/копирование-выход (copy-in/copy-out, value-result)

    На вход – копия, на выход – синхронизация изменённой копии обратно в аргумент (если он адресуем).

    • Плюсы: упрощает reasoning внутри функции (как по значению), но сохраняет эффект изменения к моменту возврата.

    • Минусы: два копирования; неоднозначность при алиасинге нескольких фактических параметров на один объект.

  5. По имени (call by name, историческая)

    Текстуальная подстановка «параметр как макро-выражение» (ALGOL 60). Вычисление откладывается до момента использования.

    • Плюсы: выражает ленивость.

    • Минусы: трудно предсказывать число вычислений и побочные эффекты; сегодня почти не используется в прикладных ЯП, важно как теория.

  6. По «совместному использованию объекта» (call by sharing)

    Формальный параметр получает ссылку на один и тот же объект, но связь с именем аргумента не передаётся (нельзя «перепривязать» исходную переменную). Типична для Python/Java (для ссылочных типов), JavaScript, многих функциональных ЯП с мутабельными структурами.

    • Следствие: изменение внутреннего состояния мутабельного объекта видно снаружи; попытка «переприсвоить параметр» не влияет на переменную вызывающего.

    • Ключ к пониманию: различайте мутабельность объекта и перепривязку имени.

Мутабельность, алиасинг и эффекты

  • Мутабельность: объекты делятся на изменяемые (списки, словари, массивы) и неизменяемые (числа, строки в ряде ЯП, кортежи).

  • Алиасинг: два параметра (или параметр и глобальная переменная) указывают на один объект. Без должной осторожности приводит к неинтуитивному поведению.

  • Правило безопасности: если функция декларирована как in, внутри неё нельзя изменять состояние аргумента; для изменяемых типов пользуйтесь копиями/защитным клонированием.

Информатика–схема передачи аргументов в функцию

Формальная семантика вызова

При вызове:

  1. Вычисляются фактические параметр(ы) в порядке, определённом языком (лево-направо, право-налево или не определён).

  2. Производится связывание с формальными параметрами (позиционное и/или именное).

  3. Создаётся активационная запись: места под формальные параметры, локальные переменные.

  4. Выполняется тело; на return (или неявном завершении) возвращается управление и, при необходимости, значение/результаты out/inout.

  5. Разрушается активационная запись (или снимается со стека).

Замечание о порядке вычисления аргументов. В ряде языков он не определён стандартом. Не полагайтесь на побочные эффекты в выражениях аргументов.

Правила корректного проектирования

  1. Контракты in/out/inout. На уровне спецификации фиксируйте направление передачи. Для in – гарантируйте отсутствие модификаций; для out/inout – опишите постусловия.

  2. Константность интерфейса. Если изменения не требуются – используйте константные ссылки (или не мутабельные типы) даже при передаче «по ссылке» с целью экономии копирования.

  3. Защитное копирование. При сомнениях в источнике аргумента (особенно если объект разделяется) делайте «копию для записи» (copy-on-write).

  4. Запрет на «скрытые эффекты». Не модифицируйте аргументы без явного указания в спецификации; это критично для доказуемости и тестируемости.

  5. Чёткая политика по умолчанию. Значения по умолчанию не должны быть мутабельными объектами (классическая ловушка Python: общая разделяемая структура между вызовами).

  6. Чёткая стоимость. Для больших структур (массивы, строки) явно оценивайте цену копирования; передавайте по ссылке/указателю, если копия не нужна.

  7. Избегайте алиасинга параметров. Если два формальных параметра могут ссылаться на один объект, сделайте копию или запретите такую ситуацию пред-/постусловиями.

  8. Нулевая стоимость абстракции. Для «горячих» путей используйте перемещение/взятые по ссылке представления, чтобы вызов не увеличивал асимптотику.

Типовые идиомы

  1. swap

    • По значению – не обменяет исходные переменные, нужен возврат пары или ссылки/указатели.

    • По ссылке – честный обмен без возврата.

    • По sharing – переприсвоение параметра не влияет на аргумент; менять нужно внутреннее состояние объекта.

  2. Агрегирующие «аккумуляторы»

    Передавайте аккумулятор как inout (или возвращайте новое значение). Запрещено полагаться на побочный эффект «глобальной» переменной.

  3. «Функция чистая снаружи – быстрая внутри»

    Интерфейс in + локальная копия, если внутри нужно мутабельное представление (например, буферизованная обработка строки).

  4. Позиционные и именованные аргументы

    Для читабельности и устойчивости к рефакторингу предпочитайте именованные в вызовах с множеством однотипных параметров.

  5. Ловушка «мутабельное по умолчанию»

    # Неправильно:

    def f(x, acc=[]): acc.append(x); return acc

    # Правильно:

    def f(x, acc=None):

        if acc is None: acc = []

        acc.append(x); return acc

Связь с подготовкой к ЕГЭ по информатике

На ЕГЭ регулярно встречаются задания, где требуется:

  • Трассировка вызовов и вычисление результата функции с параметрами (включая вложенные вызовы).

  • Понимание семантики изменения аргументов: вернётся ли обновлённый массив/строка? Нужно ли возвращать новое значение?

  • Оценка стоимости: сколько операций выполнится при передаче большого массива «по значению» (модельно) и как это влияет на асимптотику решения.

  • Преобразование решения: из «модифицируем аргумент» в «возвращаем новое значение» и обратно, с корректной работой со ссылками.

  • Работа с файлами/массивами: функции, принимающие пути/потоки/срезы, – аккуратная спецификация in/out.

  • Доказательство корректности: формулирование предусловий и постусловий на параметры (например, «массив отсортирован», «индексы корректны»).

Псевдокод (межъязыковой)

  1. По значению vs по ссылке

    procedure inc_by_value(x):      // x – копия

      x := x + 1

    procedure inc_by_ref(var x):    // x – ссылка на аргумент

      x := x + 1

    a := 5

    inc_by_value(a)  // a = 5

    inc_by_ref(a)    // a = 6

  2. По sharing (мутабельный объект)

    procedure add_front(L, item):   // L – ссылка на тот же список (sharing)

      L.prepend(item)               // изменяется исходный список

    procedure rebind(L, new_list):  // перепривязка формального параметра

      L := new_list                 // не влияет на переменную вызывающего

  3. Копирование-вход/копирование-выход

    procedure normalize(value-result V):

      V := V / max(1, abs(V))       // внутренняя работа с копией

    // По возврате V синхронизируется назад

  4. Контракты

    procedure sum_prefix(const A[0..n-1], in k) returns s

      require 0 <= k <= n

      ensure s = Σ_{i=0}^{k-1} A[i]

Оценка сложности и ресурсы

  • Время вызова: создание кадра стека O(1); стоимость передачи = O(1) для скаляров/ссылок, O(n) для больших структур при копировании.

  • Память: параметры по значению занимают место под копии; по ссылке – под указатели/ссылки; рекурсия – глубина стека O(depth).

  • Оптимизации: перемещение/заимствование (move), «нулевые копии», sso/rope для строк – теоретически снижают накладные расходы, но на экзамене опирайтесь на абстрактную модель стоимости копирования.

Типичные ошибки

  1. Ожидание, что по значению изменится аргумент вызова. Лечение: возвращайте новое значение или используйте inout.

  2. Неосознанная модификация общего объекта при sharing. Делайте защитную копию, если нужен локальный эффект.

  3. Мутабельный параметр по умолчанию. Применяйте None/специальный маркер и создавайте объект внутри.

  4. Алиасинг двух параметров на один объект. Фиксируйте запрет или клонируйте.

  5. Побочные эффекты в выражениях аргументов при неопределённом порядке вычисления. Выносите эффекты до вызова.

  6. Смешение уровней абстракции: «функция чистая» по контракту, но меняет глобальное состояние/аргумент.

Практикум: 5 упражнений (ЕГЭ-формат)

Упражнение 1. Трассировка по значению и по ссылке
Условие.
Дан псевдокод:

procedure F_by_val(x, y):

  x := x + y

  y := x - y

procedure F_by_ref(var x, var y):

  x := x + y

  y := x - y

a := 2; b := 5

F_by_val(a, b)

F_by_ref(a, b)

print a, b

Определите вывод.
Критерии. Корректное различение копий и ссылок; аккуратная трассировка.
Подсказки. После F_by_val a,b не меняются; после F_by_ref меняются оба.

Упражнение 2. Мутабельность и sharing
Условие.

procedure push_front(L, v):   // sharing

  L.prepend(v)

procedure assign_new(L):      // попытка перепривязки

  L := [0]

S := [1,2,3]

push_front(S, -1)

assign_new(S)

print S

Что будет напечатано? Объясните.
Критерии. Понимание, что модификация внутреннего состояния списка видна, а перепривязка формального параметра – нет.
Подсказки. Ответ должен содержать список из 4 элементов, начинающийся с -1.

Упражнение 3. Ловушка значения по умолчанию
Условие.

function collect(x, acc = []):

  acc.append(x)

  return acc

print collect(1)

print collect(2)

  1. Каков фактический вывод? 2) Исправьте функцию без изменения интерфейса.
    Критерии. Выявление разделяемого объекта по умолчанию; корректное исправление через «сентинел» (None) и создание нового списка.
    Подсказки. Второй вывод не должен «накапливать» результат первого.

Упражнение 4. Стоимость копирования
Условие.
Функция H(A) по значению принимает массив из n целых и выполняет k проходов линейной обработки (без дополнительных копий). Оцените суммарное время в терминах n и k, если копирование массива на входе стоит cn, а один линейный проход – dn.
Критерии. Корректная сумма: cn + k·dn; вывод о преимуществах передачи по ссылке при больших n.
Подсказки. Учтите только одно копирование на входе (функция не копирует далее).

Упражнение 5. Контракты in/out/inout
Условие.
Спроектируйте спецификацию процедуры normalize_inplace(var A), которая масштабирует все элементы массива так, чтобы максимальный по модулю стал равен 1, и возвращает число изменений. Укажите:
(a) предусловия; (b) постусловия; (c) направление параметров; (d) поведение на пустом массиве.
Критерии. Ясное разделение in (ничего), out (счётчик изменений), inout (массив); корректная обработка нулевого максимума (max=0).
Подсказки. При max=0 массив оставляем без изменений; возвращаем 0.

Заключение

Передача аргументов – не техническая деталь, а часть контракта алгоритма, определяющая наблюдаемое поведение, стоимость и доказуемость. Осознанный выбор семантики (значение/ссылка/указатель/sharing), дисциплина мутабельности, формулирование направлений in/out/inout и аккуратная работа с алиасингом обеспечивают корректность и эффективность программ. В логике ЕГЭ это выражается в умении трассировать код, предсказывать побочные эффекты, оценивать стоимость копирования и преобразовывать решения между различными моделями передачи. Освоив предложенные правила и отработав упражнения, выпускник получает устойчивые навыки проектирования интерфейсов функций и уверенно решает задачи повышенной сложности.