Jump to content

Аргумент по умолчанию

В компьютерном программировании аргумент по умолчанию — это аргумент функции , который программисту не требуется указывать. В большинстве языков программирования функции могут принимать один или несколько аргументов. Обычно каждый аргумент должен быть указан полностью (это относится к языку программирования C). [1] ). Более поздние языки (например, C++ ) позволяют программисту указывать аргументы по умолчанию, которые всегда имеют значение, даже если оно не указано при вызове функции.

Аргументы по умолчанию в C++

[ редактировать ]

Рассмотрим следующее объявление функции:

int MyFunc(int a, int b, int c = 12);

Эта функция принимает три аргумента, из которых последний имеет значение по умолчанию двенадцать. Программист может вызвать эту функцию двумя способами:

int result = MyFunc(1, 2, 3);
result = MyFunc(1, 2);

В первом случае значение аргумента c указывается явно. значение по умолчанию 12 Во втором случае аргумент опускается и вместо него будет использоваться . Для вызываемой функции невозможно узнать, был ли аргумент указан вызывающей стороной или использовалось значение по умолчанию.

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

void PrintGreeting(std::ostream& stream = std::cout) {
  // This outputs a message to the given stream.
  stream << "hello world!";
}

Вызов функции:

PrintGreeting();

по умолчанию напечатает « hello world !» на стандартный вывод std::cout (обычно экран). С другой стороны, любой объект типа std::ostream теперь можно передать той же функции, и функция будет печатать в заданный поток, а не в стандартный вывод. В приведенном ниже примере задается std::ostream& к std::cerrи, таким образом, печатает выходные данные в виде стандартного потока ошибок.

PrintGreeting(std::cerr);

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

struct Base {
  virtual std::pair<int, int> Foo(int x = 1) {
    return {x, 1};
  }
};

struct Derived : public Base {
  std::pair<int, int> Foo(int x = 2) override {
    return {x, 2};
  }
};

int main() {
  Derived d;
  Base& b = d;
  assert(d.Foo() == std::make_pair(2, 2));
  assert(b.Foo() == std::make_pair(1, 2));
}

Перегруженные методы

[ редактировать ]

Некоторые языки, например Java , не имеют аргументов по умолчанию. Однако то же поведение можно смоделировать, используя перегрузку методов для создания перегруженных методов с тем же именем, которые принимают разное количество аргументов; а версии с меньшим количеством аргументов просто вызывают версии с большим количеством аргументов, используя аргументы по умолчанию в качестве отсутствующих аргументов:

int MyFunc(int a, int b) { return MyFunc(a, b, 12); }
int MyFunc(int a, int b, int c) { /* main implementation here */ }

Однако, помимо нескольких других недостатков , поскольку аргументы по умолчанию не моделируются в системе типов, тип обратного вызова (также известный как функция более высокого порядка) не может выразить, что он принимает какую-либо из перегрузок, или имитировать аргументы по умолчанию с помощью перегруженные функции. В то время как в JavaScript определение неперегруженной функции может заменить значение по умолчанию, когда входное значение равно undefined (независимо от того, было ли это неявно undefined из-за отсутствия аргумента на месте вызова или явно переданного undefined ценить); который моделируется как необязательный тип параметра аргумента ?: в TypeScript . Решение JavaScript не разрешается статически (т. е. не во время компиляции, поэтому TypeScript моделирует только необязательность, а не значения по умолчанию в сигнатуре типа функции), что влечет за собой дополнительные накладные расходы во время выполнения, хотя и обеспечивает большую гибкость, поскольку обратные вызовы могут независимо друг от друга выполняться. контролируют их значения по умолчанию, а не централизованно диктуются сигнатурой типа (сигнатуры обратного вызова в) сигнатуре типа функции, которая вводит обратный вызов. Решение TypeScript можно смоделировать на Java с помощью Optional тип, кроме аналога неявного undefined для каждого отсутствующего аргумента является явным Optional.<Integer>absent() на месте вызова.

Для каждого вызова функции значения аргументов по умолчанию должны передаваться вызываемой функции. Если значение аргумента по умолчанию содержит побочные эффекты, это важно, когда эти побочные эффекты оцениваются — один раз для всей программы (во время анализа, компиляции или загрузки) или один раз для каждого вызова функции, во время вызова.

Python — это известный язык, который оценивает выражения в аргументах по умолчанию один раз, во время вычисления объявления функции. Если требуется оценка для каждого вызова функции, ее можно воспроизвести, задав аргументом по умолчанию контрольное значение , например None, а затем тело функции оценивает побочные эффекты значения по умолчанию, только если было передано контрольное значение.

Например:

import random

def eager(a=random.random()):
    return a

x = eager()
y = eager()
assert x == y

def lazy(a=None):
    if a is None:
        a = random.random()
    return a

x = lazy()
y = lazy()
assert x != y

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

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

Такое поведение встречается в Python для изменяемых типов, таких как списки. Как и в случае с оценкой, чтобы обеспечить тот же размер, что и у локальной переменной, можно использовать контрольное значение:

def eager(a=[]):
    return a

x = eager()
x += [1]
assert eager() == [1]

def lazy(a=None):
    if a is None:
        a = []
    return a

x = lazy()
x += [1]
assert lazy() == []
  1. ^ Лесли, Мартин. «Параметры по умолчанию» . Справочник по программированию на C++ . Архивировано из оригинала 9 октября 2011 года . Проверено 13 января 2012 г.
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 6decabd3e712e8630056aacebe2e87eb__1710403020
URL1:https://arc.ask3.ru/arc/aa/6d/eb/6decabd3e712e8630056aacebe2e87eb.html
Заголовок, (Title) документа по адресу, URL1:
Default argument - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)