Ready to practice?
Sign up to access interactive coding exercises and track your progress.
Default Arguments
Provide optional parameter values that callers can omit.
What Are Default Arguments?
A default argument is a fallback value assigned to a function parameter. When a caller doesn't provide a value for that parameter, the default is used automatically.
Here's an example:
void display(int width, int height=25) // 25 is the default for height
{
std::cout << "Width: " << width << '\n';
std::cout << "Height: " << height << '\n';
}
When calling this function, you can choose to provide the second argument or let it use the default:
#include <iostream>
void display(int width, int height=25)
{
std::cout << "Width: " << width << '\n';
std::cout << "Height: " << height << '\n';
}
int main()
{
display(80, 50); // uses caller's value: 50
display(120); // uses default value: 25
return 0;
}
Output:
Width: 80
Height: 50
Width: 120
Height: 25
The first call provides both arguments explicitly. The second call omits the second argument, so the default value of 25 is used.
Note the syntax: default arguments must use the equals sign (=). Parentheses or braces don't work:
void alpha(int value = 7); // OK
void beta(int value ( 7 )); // Compile error
void gamma(int value { 7 }); // Compile error
The compiler inserts default arguments at the call site. When it sees
display(120), it rewrites it as display(120, 25) before compiling.
When to Use Default Arguments
Default arguments are ideal when a parameter has a sensible default but you want to allow callers to override it when necessary.
Examples:
int simulateDiceRoll(int faces=6);
void openFile(std::string path="output.txt");
Default arguments are also valuable when adding parameters to existing functions. Adding a parameter without a default breaks all existing calls. Adding one with a default keeps existing calls working while allowing new code to specify custom values.
Multiple Default Arguments
Functions can have multiple parameters with defaults:
#include <iostream>
void configure(int speed=100, int volume=50, int brightness=75)
{
std::cout << "Settings: " << speed << " " << volume << " " << brightness << '\n';
}
int main()
{
configure(200, 80, 90); // all explicit
configure(200, 80); // brightness defaults to 75
configure(200); // volume and brightness use defaults
configure(); // all use defaults
return 0;
}
Output:
Settings: 200 80 90
Settings: 200 80 75
Settings: 200 50 75
Settings: 100 50 75
C++ doesn't support skipping arguments (like configure(,,90)). This has important implications:
1. Arguments must be provided left-to-right
You cannot skip an argument to provide one further right:
void setup(std::string_view name="Server", double timeout=5.0);
int main()
{
setup(); // OK: both defaulted
setup("Database"); // OK: timeout defaults to 5.0
setup(10.0); // Error: cannot skip name to provide timeout
return 0;
}
2. Parameters with defaults must be rightmost
If one parameter has a default, all parameters to its right must also have defaults:
void process(int required, int optional=10); // OK
void invalid(int optional=10, int required); // Error
Once a parameter has a default argument, all subsequent parameters must also have defaults.
3. Order matters
Place the parameter most likely to be customized on the left, since leftmost parameters are easier to override.
Declaration Rules
Default arguments cannot be redeclared in the same translation unit. You can declare them in either the forward declaration or the definition, but not both:
#include <iostream>
void display(int width, int height=25); // forward declaration
void display(int width, int height=25) // Error: redefinition
{
std::cout << "Width: " << width << '\n';
std::cout << "Height: " << height << '\n';
}
Default arguments must be declared before they're used:
#include <iostream>
void display(int width, int height); // no default yet
int main()
{
display(100); // Error: default not visible here
return 0;
}
void display(int width, int height=25)
{
std::cout << "Width: " << width << '\n';
std::cout << "Height: " << height << '\n';
}
Put default arguments in the forward declaration (especially in header files) rather than in the definition. This makes them visible wherever the function is used.
Example:
In graphics.h:
#pragma once
void display(int width, int height=25);
In main.cpp:
#include "graphics.h"
#include <iostream>
void display(int width, int height)
{
std::cout << "Width: " << width << '\n';
std::cout << "Height: " << height << '\n';
}
int main()
{
display(100); // Works because default is in header
return 0;
}
Default Arguments and Overloading
Functions with default arguments can be overloaded:
#include <iostream>
#include <string_view>
void output(std::string_view text)
{
std::cout << text << '\n';
}
void output(char character = '*')
{
std::cout << character << '\n';
}
int main()
{
output("Welcome"); // resolves to output(std::string_view)
output('X'); // resolves to output(char)
output(); // resolves to output(char) with default '*'
return 0;
}
Default values aren't part of a function's signature, so these overloads are distinct:
void process(int value); // signature: process(int)
void process(int value, int count = 5); // signature: process(int, int)
void process(int value, double scale = 2.0); // signature: process(int, double)
Ambiguity Risks
Default arguments can create ambiguous calls:
void compute(int value = 0)
{
}
void compute(double value = 0.0)
{
}
int main()
{
compute(); // Ambiguous: compute(0) or compute(0.0)?
return 0;
}
More complex example:
void process(int value);
void process(int value, int quantity = 10);
void process(int value, double multiplier = 1.5);
int main()
{
process(5, 8); // OK: resolves to process(int, int)
process(5, 3.2); // OK: resolves to process(int, double)
process(5); // Ambiguous: which overload?
return 0;
}
The call process(5) could match process(int), process(int, int), or process(int, double). The compiler cannot choose, resulting in an error.
Design your overloads carefully to avoid ambiguity when using default arguments. Test that all intended call patterns compile successfully.
Summary
Default arguments provide fallback values for function parameters:
Syntax and Rules:
- Use
=to specify default values:void func(int x = 10) - Parameters with defaults must be rightmost
- Cannot skip arguments; must provide left-to-right
- Declare defaults in headers, not definitions
Best Practices:
- Use defaults for parameters with sensible fallback values
- Place most-likely-to-change parameters leftmost
- Be careful combining defaults with overloading to avoid ambiguity
Declaration Rules:
- Default can appear in declaration OR definition, not both
- Must be visible before use (put in header files)
- Not part of function signature for overload differentiation
Default Arguments - Quiz
Test your understanding of the lesson.
Practice Exercises
Default Arguments
Create functions with default arguments to provide flexible parameter handling.
Lesson Discussion
Share your thoughts and questions
No comments yet. Be the first to share your thoughts!