вызов функции с параметром по умолчанию

Я написал экзамен по программированию на C++. Был один вопрос, в котором я и мой профессор не согласились. Вопрос заключался в том, работает ли следующая функция или нет:

#include <iostream>
using namespace std;

void f(int=4, long=10, double=3.14);

int main( int argc , char ** argv )
{
    f( , ,8);
      return EXIT_SUCCESS;
}

void f(int i, long l, double d) {
    cout << i << " " << " " << l << " " << d;
}

Я сказал, что это не сработает, но мой профессор сказал, что это определенно сработает из-за параметра по умолчанию в объявлении функции. Я попробовал это с MSVC, и это не сработало. Это зависит от компилятора? Как я могу убедить своего профессора, что это не работает ни в одном компиляторе, чтобы повысить свою оценку на экзамене?


person tzwickl    schedule 22.05.2013    source источник


Ответы (4)


Начнем с того, что вы правы, профессор ошибается. И тот факт, что он утверждает, что это должно работать (когда тривиально показать, что это не так), означает, что ему, вероятно, не следует преподавать C++. Но как его показать?

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

Если это не удается, укажите стандарт C++. Вот синтаксис выражения вызова, как описано в [expr.post]p1 и после нетерминальных ссылок:

postfix-expression:
    ...
    postfix-expression ( expression-list[opt] )

expression-list:
    initializer-list

initializer-list: ([dcl.init]p1)
    initializer-clause ...[opt]
    initializer-list , initializer-clause ...[opt]

initializer-clause:
    assignment-expression
    braced-init-list

braced-init-list:
    { initializer-list ,[opt] }
    { }

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

person Sebastian Redl    schedule 22.05.2013
comment
Спасибо, теперь я в состоянии предоставить идеальные контраргументы - person tzwickl; 22.05.2013

Из Стандарта (выделено мной, особенно обратите внимание на слово trailing):

8.3.6 Аргументы по умолчанию [dcl.fct.default]

  1. Если в объявлении параметра указано предложение-инициализатор, то это предложение-инициализатор используется в качестве аргумента по умолчанию. Аргументы по умолчанию будут использоваться в вызовах, в которых отсутствуют завершающие аргументы.

  2. [ Пример: декларация

void point(int = 3, int = 4);

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

point(1,2); point(1); point();

Последние два вызова эквивалентны point(1,4) и point(3,4) соответственно.

— конец примера]

Наслаждайтесь возвращением своих баллов. ;)

person syam    schedule 22.05.2013
comment
Спасибо за то, что разрешено опускать только конечные аргументы, звучит как хороший аргумент :) Я попытаюсь объяснить ему это таким образом. - person tzwickl; 22.05.2013

Это даже недействительный синтаксис С++.

person Kerrek SB    schedule 22.05.2013
comment
@tom1991te: Вы не можете сказать f( , , 8). Это не разрешено. - person Kerrek SB; 22.05.2013
comment
Да, я точно знаю, что это был мой вопрос :) Я знаю, что это неверно, но мой профессор этого не знает: D - person tzwickl; 22.05.2013
comment
@KerrekSB: не это бессмысленно, поскольку из-за этого профессор снял баллы с теста ОП. ;) - person syam; 22.05.2013

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

f(); // should use all default values for arguments
f(3); // should use 3 for the first, default for the last two 
f(2, 5); // uses 2 for first, 5 for second, default for last
f(5, 6, 3.4); // does not use any default values
person tay10r    schedule 22.05.2013