stringtranslate.com

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

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

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

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

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

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

int result = MyFunc ( 1 , 2 , 3 ); результат = MyFunc ( 1 , 2 );        

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

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

void PrintGreeting ( std :: ostream & stream = std :: cout ) { // Это выводит сообщение в данный поток. поток << "Привет, мир!" ; }         

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

РаспечататьПриветствие ();

по умолчанию напечатает « 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 () { Производное d ; База & 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 ) { /* здесь основная реализация */ }                   

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

Оценка

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

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

Например:

импортировать  случайныйdef  нетерпеливый ( a = случайный . случайный ())  : вернуть x  =  нетерпеливый () y  =  нетерпеливый () утверждать  x  ==  ydef  lazy ( a = None ):  если  a  равно  None :  a  =  random . случайный (  ) возвращает x  =  ленивый () y  =  ленивый () утверждать  x  !=  y

Степень

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

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

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

def  нетерпелив ( a = []):  вернуть  ax  =  нетерпеливый () x  +=  [ 1 ] утверждать  нетерпеливый ()  ==  [ 1 ]def  lazy ( a = None ):  если  a  равно  None :  a  =  []  вернуть  ax  =  ленивый () x  +=  [ 1 ] утверждать  ленивый ()  ==  []

Рекомендации

  1. ^ Лесли, Мартин. «Параметры по умолчанию». Справочник по программированию на C++ . Архивировано из оригинала 9 октября 2011 года . Проверено 13 января 2012 г.