A default argument is a 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.
Because the user can choose whether to supply a specific argument value, or use the default, a parameter with a default value provided is often called an optional parameter.
Consider the following program:
1 2 3 4 5 6 7 8 9 10 11 |
void printValues(int x, int y=10) // 10 is the default argument, y is now an optional parameter { std::cout << "x: " << x << '\n'; std::cout << "y: " << y << '\n'; } int main() { printValues(1); // y will use default argument 10 printValues(3, 4); // y will use user-supplied argument 4 } |
This program produces the following output:
x: 1 y: 10 x: 3 y: 4
In the first function call, the caller did not supply an argument for y, so the function used the default value of 10. In the second call, the caller did supply a value for y, so the user-supplied value was used.
Default arguments are an excellent option when the function needs a value that the user may or may not want to override. For example, here are a few function prototypes for which default arguments might be commonly used:
1 2 3 |
void openLogFile(std::string filename="default.log"); int rollDie(int sides=6); void printStringInColor(std::string str, Color color=COLOR_BLACK); // Color is an enum |
Multiple default arguments
A function can have multiple default arguments:
1 2 3 4 |
void printValues(int x=10, int y=20, int z=30) { std::cout << "Values: " << x << " " << y << " " << z << '\n'; } |
Given the following function calls:
1 2 3 4 |
printValues(1, 2, 3); printValues(1, 2); printValues(1); printValues(); |
The following output is produced:
Values: 1 2 3 Values: 1 2 30 Values: 1 20 30 Values: 10 20 30
Note that it is impossible to supply an argument for parameter z without also supplying arguments for parameters x and y. This is because C++ does not support a function call syntax such as printValues(,,3)
. This has two major consequences:
1) All default arguments must be for the rightmost parameters. The following is not allowed:
1 |
void printValue(int x=10, int y); // not allowed |
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 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.
1 2 3 4 5 6 7 |
void printValues(int x, int y=10); void printValues(int x, int y=10) // error: redefinition of default argument { std::cout << "x: " << x << '\n'; std::cout << "y: " << y << '\n'; } |
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:
1 2 3 4 |
#ifndef FOO_H #define FOO_H void printValues(int x, int y=10); #endif |
in main.cpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#include "foo.h" #include <iostream> void printValues(int x, int y) { std::cout << "x: " << x << '\n'; std::cout << "y: " << y << '\n'; } int main() { printValues(5); return 0; } |
Note that in the above example, we’re able to use the default argument for function printValues() because the main.cpp #includes foo.h, which has the forward declaration that defines the default argument.
Rule
If the function has a forward declaration, put the default argument there. Otherwise, put them in the function definition.
Default arguments and function overloading
Functions with default arguments may be overloaded. For example, the following is allowed:
1 2 |
void print(std::string string); void print(char ch=' '); |
If the user were to call print()
, it would resolve to print(' ')
, which would print a space.
However, it is important to note that optional parameters do NOT count towards the parameters that make the function unique. Consequently, the following is not allowed:
1 2 |
void printValues(int x); void printValues(int x, int y=20); |
If the caller were to call printValues(10)
, the compiler would not be able to disambiguate whether the user wanted printValues(int) or printValues(int, 20) with the default value.
Summary
Default arguments provide a useful mechanism to specify parameters that the user may optionally provide values for. They are frequently used in C++, and you’ll see them a lot in future lessons.
![]() |
![]() |
![]() |
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."
>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!
Hi, Alex and Nascardriver!
This is if string passed by value
But, is this if I passed string by reference?
Yes, that's what the `&` means.
"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"
Fixed! Thanks for pointing this out.
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.
Indeed. Nomenclature changed. Thanks for pointing out the inaccuracy.
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.
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?
You can't. Default parameters must be compile-time constants, and deck is a variable.
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.
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.
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.
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.
@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
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.
char name[10];
//I want to enter default value of name like "name= jayu"how I can do that please send me syntax of this.jayupipaliya198@gmail.com
Hi Jayu!
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
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
Hi Marcus!
The only way to use default arguments is not setting them at all.
;(
Thank you nascardriver!
Short answer: no. Default values can only be invoked for the rightmost parameters in a call, and are invoked by not passing an argument for that parameter in the function call.
How does it work for map? I have a map "std::map<int,std::string> map" , how will it work for optional parameter ?
Hi Nakamura!
An std::map can be initialized with empty curly braces
Output
"void printStringInColor(std::string, Color color=COLOR_BLACK); // Color is an enum"
You forgot the parameter's, of type std::string, name.
Fixed. Even though providing the name of the parameters is optional in a function prototype (only the type is required), it's a good practice to do so.
Oh, I didn't know that...
"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.
Lesson fixed. Thanks!
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
Agreed -- I've updated and clarified the text to be clearer that I was talking about arguments, not parameters. :)
In foo.h
Shouldn't it be
Yes, fixed.
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"?
Definitely "in". You'd think I didn't proofread this stuff. I guess I just must be horrible at it. :)
Little typo on one of the function prototypes:
I'm pretty sure you meant rollDice than rollDie XD
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).
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';
}
Typo. It's fixed now, thanks for noticing.
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.
Put the default parameter in the forward declaration:
Shouldn't they be called 'Default arguments'?
They often are.
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);
No you can't.
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! :)