Search

8.12 — Default arguments

A default argument is a default value provided for a function parameter. For example:

When making a function call, the caller can optionally provide an argument for any function parameter that has a default argument. If the caller provides an argument, the value of the argument in the function call is used. If the caller does not provide an argument, the value of the default argument is used.

Consider the following program:

This program produces the following output:

x: 1
y: 2
x: 3
y: 4

In the first function call, the caller supplied explicit arguments for both parameters, so those argument values are used. In the second function call, the caller omitted the second argument, so the default value of 4 was used.

When to use default arguments

Default arguments are an excellent option when a function needs a value that has a reasonable default value, but for which you want to let the caller override if they wish.

For example, here are a couple of function prototypes for which default arguments might be commonly used:

Author's note

Because the user can choose whether to supply a specific argument value or use the default value, a parameter with a default value provided is sometimes called an optional parameter. However, the term optional parameter is also used to refer to several other types of parameters (including parameters passed by address, and parameters using std::optional), so we recommend avoiding this term.

Multiple default arguments

A function can have multiple parameters with default arguments:

The following output is produced:

Values: 1 2 3
Values: 1 2 30
Values: 1 20 30
Values: 10 20 30

C++ does not (as of C++20) support a function call syntax such as print(,,3) (as a way to provide an explicit value for z while using the default arguments for x and y. This has two major consequences:

1) Default arguments can only be supplied for the rightmost parameters. The following is not allowed:

Rule

Default arguments can only be provided for the rightmost parameters.

2) If more than one default argument exists, the leftmost default argument should be the one most likely to be explicitly set by the user.

Default arguments can not be redeclared

Once declared, a default argument can not be redeclared (in the same file). That means for a function with a forward declaration and a function definition, the default argument can be declared in either the forward declaration or the function definition, but not both.

Best practice is to declare the default argument in the forward declaration and not in the function definition, as the forward declaration is more likely to be seen by other files (particularly if it’s in a header file).

in foo.h:

in main.cpp:

Note that in the above example, we’re able to use the default argument for function print() because main.cpp #includes foo.h, which has the forward declaration that defines the default argument.

Best practice

If the function has a forward declaration (especially one in a header file), put the default argument there. Otherwise, put the default argument in the function definition.

Default arguments and function overloading

Functions with default arguments may be overloaded. For example, the following is allowed:

The function call to print() acts as if the user had explicitly called print(' '), which resolves to print(char).

Now consider this case:

Parameters with default values will differentiate a function overload (meaning the above will compile).
However, such functions can lead to potentially ambiguous function calls. For example:

In the last case, the compiler is unable to tell whether print(1) should resolve to print(int) or one of the two function calls where the second parameter has a default value. The result is an ambiguous function call.

Summary

Default arguments provide a useful mechanism to specify values for parameters that the user may or may not want to override. They are frequently used in C++, and you’ll see them a lot in future lessons.


8.13 -- Function templates
Index
8.11 -- Function overload resolution and ambiguous matches

64 comments to 8.12 — Default arguments

  • Dylan

    Hello, you said default arguments can only be declared once. This doesn't seem to be the case.

    In functionsA.cpp I have:

    in functionsA.h I have:

    then in main I have:

    it compiles fine and prints:
    1 2 4 4 3 4
    as expected.

    • Alex

      I changed the wording slightly to say it can not be redeclared in the same file. Because functionsA.cpp does not include functionsA.h, the default arguments for testPrint in functionsA are as defined in the definition. In main.cpp, the default arguments are as defined in the declaration imported from functionsA.h.

  • Haldhar Patel

    >You said before "A default argument is a default value provided for a function parameter."

    But in section "Multiple default arguments":

    [Multiple default arguments

    A function can have multiple default arguments:]

    >How can a default argument can be more than one I think it must be "Multiple optional parameters"  and also the same should be changed for the rest of the lesson , they are also used in constructor lesson and creating confusion.

    • Alex

      Updated to "A function can have multiple parameters with default arguments".

      Does that help, or is your point of confusion elsewhere?

      • Haldhar Patel

        It makes sense now, also if the section name "Multiple default arguments" could be changed to "Multiple parameters with default arguments" , it will be more clear but it's completely from my perspective at least and  no other have found difficult to understand this{Multiple default arguments is also understandable} , so you don't need to change anymore.

        Also they are not creating any confusion to me now in other sections too, I wanted to edit my comment{in the time limit} but due to caching issue I was not able to because it didn't load my comment after reloading the page.

  • rez

    Hi Alex and nascardriver.
    I wonder why I can not use brace initialization syntax in function parameters?

    • Alex

      I was wondering the same thing earlier this week. I presume there is some case where use of {} leads to ambiguity in parsing the function declaration.

  • EternalSkid

    Hello Alex and nascardriver,I am curious on will this make a difference?

    Best practice is to declare the default argument in the forward declaration and not in the function definition, as the forward declaration is more likely to be seen by other files (particularly if it’s in a header file).

    When the compiler reaches the function call, won't it still have to jump back to the function defined in a source file? If so, why will declaring the default arguments in the function declaration help that much?

    EDIT : I've just tried it myself, and it didn't work. Are you able to explain why?

    Header.h

    source.cpp

    main.cpp

    Error code : 'printValues': function does not take 1 arguments

    Thanks so much!

    • EternalSkid

      Hey Alex and nascardriver, are you able to explain this to me? Thanks!

      • Alex

        When main is compiled, it only sees this:

        Clearly there's a mismatch between the number of parameters in the call vs the forward declaration.

        > When the compiler reaches the function call, won't it still have to jump back to the function defined in a source file

        No, the compiler is satisfied by the forward declaration. The linker does the work of connecting the function call to the actual function definition in another source file.

      • EternalSkid

        I see, when does the linker do that? After compilation? Thanks alex!

        • Waldo Lemmer

          The linker runs after the compiler. See https://www.learncpp.com/cpp-tutorial/introduction-to-the-compiler-linker-and-libraries/

  • Cerezas

    The following rule is looking forward to inhabiting its shiny new green box home ;)
    "Rule: If the function has a forward declaration, put the default argument there. Otherwise, put them in the function definition."

  • terapty

    >However, it is important to note that optional parameters do NOT count towards the parameters that make the function unique.

    Just as a sidenote, forward declaring or defining functions with signatures that only differ by the TYPE of last default parameters is still ambiguous.
    And it makes sense, the compiler should tell you it's impossible to make any call to the function unambiguously if you only specify the non-"defaultable" arguments when you call it (the compiler would have to "guess" which overloaded function you're trying to call).

    Example, just to clarify...

    In foo.h:

    In foo.c:

    Compiling with gcc version 7.4.0 :
    foo.c:15:18: error: call of overloaded ‘printValues(int)’ is ambiguous

    Then it procedes to list all ambiguous candidates (in all the different headers that declare the function I suppose, but haven't tested that out).
    I think (if the author intends to update this page with this) it should be added to the last section that deals with function overloading.

    P.S. : This site is awesome. Well-written, lots of technical detail, there's also some basics on how to use the standard library and even some custom-made implementations of known algorithms.
    It not only gives you the tools to get started programming fast, it also gives you lots of C++-specific details to make sure you leverage all of its benefits and avoid its pitfalls! Nice work!

  • Samira Ferdi

    Hi, Alex and Nascardriver!

    This is if string passed by value

    But, is this if I passed string by reference?

  • Red Lightning

    "A default argument is an default value provided for a function parameter. If the user does not supply an explicit argument for a parameter with a default argument, the default value will be used. If the user does supply an argument for the parameter, the user-supplied argument is used."
    Syntax error: "a default" instead of "an default"

  • Zha Weihua

    Default arguments can only be declared once

    Once declared, a default argument can not be redeclared. That means for a function with a forward declaration and a function definition, the default argument can be declared in either the forward declaration or the function definition, but not both.

    About this conclusion, I saw an inverse example. May I think it's a C++ defect and we should avoid to use it?

    refer to
    https://stackoverflow.com/questions/44818513/c-adding-and-redefinition-of-default-arguments-in-real-world

    #include <iostream>

    void foo(int a, int b, int c = -1)
    {
        std::cout << "foo(" << a << ", " << b << ", " << c << ")\n";
    }

    int main()
    {
        foo(1, 2);   // output: foo(1, 2, -1)

        // error: does not use default from surrounding scope
        //void foo(int a, int b = 0, int c);

        void foo(int a, int b, int c = 30);
        foo(1, 2);   // output: foo(1, 2, 30)

        // error: we cannot redefine the argument in the same scope
        // void foo(int a, int b, int c = 35);

        // has a default argument for c from a previous declaration
        void foo(int a, int b = 20, int c);
        foo(1);      // output: foo(1, 20, 30)

        void foo(int a = 10, int b, int c);
        foo();       // output: foo(10, 20, 30)

        {
            // in inner scopes we can completely redefine them
            void foo(int a, int b = 4, int c = 8);
            foo(2);  // output: foo(2, 4, 8)
        }

        return 0;
    }

    • Hi!

      This is not a defect, it's explicitly allowed.
      "[...] default arguments can be added in later declarations of a function in the same scope."

      I agree, this should be avoided as it requires a reader to read the preceding code to understand a function call (As opposed to reading a single declaration).

  • Hi Alex!

    They're called default arguments, not parameters.

  • magaji::hussaini

    Hi alex I think a note should added that only copy initialisation work with default parameters because I got a compile time error when I tried uniform/direct initialisations.

  • ST.James

    In the challenge section in lesson 6 (the blackjack game), we're almost sure that each time we call shuffleDeck, we will be passing in a deck of cards (&deck); how do we make "&deck" a default parameter?

  • Peter Baum

    1. Is there any good reason why C++ does not support more flexible default values such as

    and

    ?

    2. It seems strange that “Once declared, a default parameter can not be redeclared.” even when the declarations are exactly the same.  Is there any good reason why this is not allowed?

    3. In the function overload example:

    the statement is made that “… the compiler would not be able to disambiguate…” such a situation.  Note that it could easily do this if the requirement is to write

    if the second function were desired.

    • nascardriver

      Hi Peter!

      1. I don't think there is. The boost library has a feature to explicitly use a default parameter when calling a function. I like your first suggestions, but I don't like the second one.

      2. Either you declare the parameter with the same default value twice, which is redundant, or you declare them with different default values, which doesn't make sense.

      • Peter Baum

        Hi nascardriver,
        Regarding 2... if they had different default values maybe the compiler could point out the conflict.  That would take care of the redundancy too, because the programmer could use that feature to verify that the code for each section was consistent.

        Not a big deal in any case.

        Thanks.

    • Alex

      This is a pretty common question. There's some conversation about this topic here.

      I think the short is that they could have, but it would have made the language more complex, and they didn't feel that was worth the tradeoffs.

      I do wonder if you could work around this by using std::optional, which was introduced in C++17.

      • nascardriver

        @std::optional can be used, but you'd have to set the default value in the function body which isn't where default values should be located in my opinion.
        If there is a better way I'd love to know it.

        Output
        Waldo is wearing a red shirt and is located at 12.3, 45.6
        Waldo is wearing a blue shirt and is located at 78.9, 1.2

        • Alex

          I agree. I'm not aware of a way to solve this, but I'm also not that familiar with some of the C++17 stuff, so maybe someone who is knows of a good way to resolve.

  • jayu

    char name[10];

    //I want to enter default value of name like "name= jayu"how I can do that please send me syntax of [email protected]

  • Trevor

    I should probably try it, but I would think that if a function has default arguments and is called from a different CPP file, then the default values would need to be in the function prototype. My thinking is that the default values are inserted by the compiler as it compiles the calling code, otherwise the linker would need to differentiate between calls with all the arguments and calls with missing arguments which require the default parameters.
    This would raise the interesting (and scary) prospect of being able to define different default parameter values in different CPP files by using different function prototypes for the same function! However I would not recommend using this - just include the required argument value in the call.
    Trevor

    • Alex

      I believe you are correct. This is generally avoided by putting your function prototypes in a header and #including that header wherever you need access to the function. That way you only have a single function prototype.

  • Is there an explicit way to use the default value?
    e.g printValues(-1, *, -1) where '*' means that I would like to use the default value.
    Output:
    Values: -1 20 -1

  • Nakamura

    How does it work for map? I have a map "std::map<int,std::string> map" , how will it work for optional parameter ?

    • nascardriver

      Hi Nakamura!
      An std::map can be initialized with empty curly braces

      Output

  • nikos-13

    "void printStringInColor(std::string, Color color=COLOR_BLACK); // Color is an enum"
    You forgot the parameter's, of type std::string, name.

  • "Note that it is impossible to supply a user-defined value for z without also supplying a value for x and y."
    This function refers to printValues(int x, int y, int z) so I think the sentence should be:
    "Note that it is impossible to supply a user-defined value for x without also supplying a value for y and z."
    Thanks as always.

    • Alex

      Lesson fixed. Thanks!

      • Kess

        Actually, I believe it was correct in it's former version, as in order to provide the value only for x you could just write printValues(3);
        and the function would be called with 3, 20 and 30 as its arguments (20 and 30 being the default values for y and z)

        "Note that it is impossible to supply a user-defined value for x without also supplying a value for y and z."
        Would mean that I would have to write printValues(3, 20, 30); While possible, it's easier and still correct to write printValues(3);

        "Note that it is impossible to supply a user-defined value for z without also supplying a value for x and y."
        Would mean that I cannot write printValues(,,3); which is the intended outcome of that particular part of the lesson. Also, the next sentence in the explanation makes it clear that the intention was to point out that you cannot set z while leaving x and y to their default values without at least explicitly set them (to their default value, if you need them to be that way).

        Thanks for these top notch lessons ;)
        Have a good day

  • Akshay Chavan

    In foo.h

    Shouldn't it be

  • Matt

    At the end of section "Default parameters can only be declared once", you wrote:

    "Rule: If the function has a forward declaration, put the default parameters there. Otherwise, put them on the function definition."

    Did you mean to write "on", or did you mean "in"?

  • Kattencrack Kledge

    Little typo on one of the function prototypes:

    I'm pretty sure you meant rollDice than rollDie XD

    • Alex

      Nope. Die is actually the singular of dice, and in this case, we are just rolling one die, not multiple dice. Though enough people don't know this that I suspect it will be acceptable to use dice in both situations in the near future (if we haven't hit that point already).

  • Jim

    Alex,
    This code uses the same name and parameters except one has a capital V and the other uses a lower case v.
    Why wouldn't the compiler catch this? Or is this a typo?
    [code]
    void printvalues(int x, int y=10);

    void printValues(int x, int y=10) // error: redefinition of default parameter
    {
        std::cout << "x: " << x << '\n';
        std::cout << "y: " << y << '\n';
    }

  • Alex, is there any way to forward declare a function that has default pararmeters in it...?

    [code]
    #include <iostream>

    void val(int, int);

    int main()
    {
        int value = 10;
        val(value);
        return 0;
    }

    void val(int nval, int val2 = 20)
    {
        std::cout << nval << "\n";
        std::cout << val2 << "\n";
    }

    This program gives an error at line 8:

    "Fire.cpp|8|error: too few arguments to function 'void val(int, int)'|"

    and if I remove an int, compiler says that it is unable to find a function with only 1 int parameter.

    • Alex

      Put the default parameter in the forward declaration:

  • kekie

    Shouldn't they be called 'Default arguments'?

  • Sphingine

    Can i give d definition as:

    void printvalues(int nvalue1=0, int nvalue2=2)
    {

    cout<<"1st : "<< nvalue1<< endl;
    cout<<"2st : "<< nvalue2<< endl;

    }

    and call the function as:

    printvalues(,3);

  • dave

    I must say this site is awesome and clean looking..specially how the code is displayed....looks neat! keep up good work and i am doing last min craming when i googled default params...so wish me luck! :)

Leave a Comment

Put all code inside code tags: [code]your code here[/code]