Permite llamar a una función sin proporcionar uno o más argumentos finales.

Indicado mediante el uso de la siguiente sintaxis para un parámetro en el lista de parámetros de una declaración de función.

attr(Opcional)decl-specifier-seqdeclarador= inicializador (1)
attr(Opcional)decl-specifier-seqdeclarador-abstracto(Opcional)= inicializador (2)

Los argumentos predeterminados se utilizan en lugar de los argumentos finales que faltan en una llamada de función:

voidpoint(int x =3,int y =4);point(1,2);// calls point(1,2)point(1);// calls point(1,4)point();// calls point(3,4)

En una declaración de función, después de un parámetro con un argumento predeterminado, todos los parámetros posteriores deben hacerlo.

  • tener un argumento predeterminado proporcionado en esta declaración o en una declaración anterior del mismo alcance
intx(int=1,int);// error, assuming there's no previous declaration of xvoidf(int n,int k =1);voidf(int n =0,int k);// OK: k's default supplied by previous decl in the same scopevoidg(int,int=7);voidh()voidg(int=1,int);// Error: not the same scope
  • … a menos que el parámetro se haya expandido desde un paquete de parámetros
template<class...T>structCvoidf(int n =0, T...);;
C<int> c;// OK; instantiates declaration void C::f(int n = 0, int)
  • o ser un paquete de parámetros de función.
template<class...T>voidh(int i =0, T... args);// ok
(desde C ++ 11)

La elipsis no es un parámetro, por lo que puede seguir a un parámetro con un argumento predeterminado.

intg(int n =0,...);// ok

Los argumentos predeterminados solo se permiten en las listas de parámetros de las declaraciones de funciones y expresiones lambda,(desde C ++ 14) y no están permitidos en las declaraciones de punteros a funciones, referencias a funciones o en declaraciones typedef. Las listas de parámetros de plantilla utilizan una sintaxis similar para sus argumentos de plantilla predeterminados.

Para las funciones que no son de plantilla, se pueden agregar argumentos predeterminados a una función que ya fue declarada si la función se vuelve a declarar en el mismo ámbito. En el momento de la llamada a una función, los valores predeterminados son una unión de los valores predeterminados proporcionados en todas las declaraciones visibles de la función. Una redeclaración no puede introducir un valor predeterminado para un argumento para el que ya es visible un valor predeterminado (incluso si el valor es el mismo). Una nueva declaración en un ámbito interno no adquiere los argumentos predeterminados de los ámbitos externos.

voidf(int,int);// #1 voidf(int,int=7);// #2 OK: adds a defaultvoidh()f(3);// #1 and #2 are in scope; makes a call to f(3,7)voidf(int=1,int);// Error: inner scope declarations don't acquire defaultsvoidm()// new scope beginsvoidf(int,int);// inner scope declaration; has no defaults.f(4);// Error: not enough arguments to call f(int, int)voidf(int,int=6);f(4);// OK: calls f(4,6);voidf(int,int=6);// Error: cannot redeclare a default in the same scopevoidf(int=1,int);// #3 OK, adds a default to #2voidn()// new scope begins f();// #1, #2, and #3 are in scope: calls f(1, 7);

Si una función en línea se declara en diferentes unidades de traducción, los conjuntos acumulados de argumentos predeterminados deben ser los mismos al final de cada unidad de traducción.

Si una declaración de amigo especifica un valor predeterminado, debe ser una definición de función de amigo y no se permiten otras declaraciones de esta función en la unidad de traducción.

La declaración using lleva el conjunto de argumentos predeterminados conocidos, y si se agregan más argumentos más adelante al espacio de nombres de la función, esos valores predeterminados también son visibles en cualquier lugar donde sea visible la declaración using.

namespace N voidf(int,int=1);using N::f;voidg()f(7);// calls f(7, 1);f();// errornamespace N voidf(int=2,int);voidh()f();// calls f(2, 1);

Los nombres utilizados en los argumentos predeterminados se buscan, se comprueba la accesibilidad y se enlazan en el punto de declaración, pero se ejecutan en el punto de la llamada a la función:

int a =1;intf(int);intg(int x =f(a));// lookup for f finds ::f, lookup for a finds ::a// the value of ::a, which is 1 at this point, is not usedvoidh()
  a =2;// changes the value of ::aint a =3;g();// calls f(2), then calls g() with the result

Para una función miembro de una clase que no es de plantilla, los argumentos predeterminados están permitidos en la definición fuera de clase y se combinan con los argumentos predeterminados proporcionados por la declaración dentro del cuerpo de la clase. Si estos valores predeterminados fuera de clase convirtieran una función miembro en un constructor predeterminado, copiar o mover, el programa está mal formado. Para las funciones miembro de las plantillas de clase, todos los valores predeterminados deben proporcionarse en la declaración inicial de la función miembro.

classCvoidf(int i =3);voidg(int i,int j =99);C(int arg);// non-default constructor;voidC::f(int i =3)// error: default argument already// specified in class scopevoidC::g(int i =88,int j)// OK: in this translation unit,// C::g can be called with no argumentC::C(int arg =1)// Error: turns this into a default constructor

Los reemplazos de funciones virtuales no adquieren los argumentos predeterminados de las declaraciones de la clase base, y cuando se realiza la llamada a la función virtual, los argumentos predeterminados se deciden en función de la static tipo de objeto (nota: esto se puede evitar con interfaz no virtual patrón).

structBasevirtualvoidf(int a =7);;structDerived:Basevoidf(int a)override;;voidm()
    Derived d;
    Base& b = d;
    b.f();// OK: calls Derived::f(7) 
    d.f();// Error: no default 

Las variables locales no están permitidas en los argumentos predeterminados. a menos que se use en un contexto no evaluado(desde C ++ 14):

voidf()int n =1;externvoidg(int x = n);// error: local variable cannot be a defaultexternvoidh(int x =sizeof n);// OK as of CWG 2082

Este puntero no está permitido en los argumentos predeterminados:

classAvoidf(A* p =this)// error: this is not allowed;

No-static los miembros de la clase no están permitidos en los argumentos predeterminados (incluso si no se evalúan), excepto cuando se usan para formar un puntero a miembro o en una expresión de acceso de miembro.

int b;classXint a;intmem1(int i = a);// error: non-static member cannot be usedintmem2(int i = b);// OK: lookup finds X::b, the static memberstaticint b;;

Los parámetros de función no están permitidos en los argumentos predeterminados (incluso si no son evaluados)(hasta C ++ 14) excepto si no están evaluados(desde C ++ 14). Tenga en cuenta que los parámetros que aparecen anteriormente en la lista de parámetros están dentro del alcance:

int a;intf(int a,int b = a);// Error: the parameter a used in a default argumentintg(int a,int b =sizeof a);// Error until CWG 2082// OK after CWG 2082: use in unevaluated context is OK

Los argumentos predeterminados no forman parte del tipo de función.

intf(int=0);voidh()int j =f(1);int k =f();// calls f(0);int(*p1)(int)=&f;int(*p2)()=&f;//Error: the type of f is int(int)

Si una expresión lambda aparece en un argumento predeterminado, no puede capturar nada explícita o implícitamente.

voidf2()int i =1;voidg1(int=([i]return i;)());// error: captures somethingvoidg2(int=([i]return0;)());// error: captures somethingvoidg3(int=([=]return i;)());// error: captures somethingvoidg4(int=([=]return0;)());// OK: capture-lessvoidg5(int=([]returnsizeof i;)());// OK: capture-less

Las funciones de operador no deben tener argumentos predeterminados, excepto para el operador de llamada de función.

classCintoperator[](int i =0);// ill-formedintoperator()(int x =0);// ok;

Informes de defectos

Los siguientes informes de defectos que cambian el comportamiento se aplicaron retroactivamente a los estándares C ++ publicados anteriormente.

DR Aplicado a Comportamiento según lo publicado Comportamiento correcto
CWG 2082 C ++ 14 Los argumentos predeterminados estaban prohibidos para usar locales en un contexto no evaluado. uso de contexto no evaluado permitido