Parameters vs Arguments
Detailed Explanation
Parameters are the variables declared in the function signature. They act as placeholders for the values that will be passed to the function. Parameters define the function's interface—what kind of data it expects to receive.
Arguments are the actual values passed to the function when it's called. They must be **compatible** with the parameter types (implicit conversions may apply) and appear in the correct **order** and **count**—unless some parameters have default arguments or a parameter pack is used.
Aspect | Parameter | Argument |
---|---|---|
Definition | Variable in function declaration/definition | Value/expression passed during call |
Lifetime | Exists only for the duration of the function call (automatic storage for the parameter itself) | Exists in the caller; temporaries can be created for the call (lifetime may extend for a bound const& only until end of the full-expression) |
Memory | Storage for the parameter is created when the function is invoked | May be an existing object, a literal, or a temporary produced by an expression |
Type Matching | Type is fixed by the function signature | Must be convertible to the parameter type (implicit conversions and promotions may occur) |
Modification | Modifying a by-value parameter affects only the local copy; modifying a reference or pointer parameter can affect the original object | Original value is unaffected unless passed by reference or via a pointer to non-const (or if the argument itself is a modifiable object passed by reference) |
Advanced Considerations
In C++, parameters can be passed by value, reference, or pointer—each with different implications for copying, aliasing, and mutability.
Modern guidance: pass small/trivial types by value; pass large objects by `const&` to avoid copies when you only need to read; use `T&&` (rvalue reference) and `std::move`/`std::forward` when you can benefit from moves.
Default arguments let callers omit trailing arguments; they are specified on declarations (not repeated across multiple declarations in the same scope).
// Parameter kinds
#include <string>
#include <utility>
void process(int byValue, // copy of argument
int& byRef, // refers to caller's object
const int& constRef) // refers to caller's object (read-only)
{
byValue++; // local only
byRef++; // changes caller's value
// constRef++; // error: read-only
}
// Pass-by-value with move for ownership/retention
struct Sink {
std::string data;
explicit Sink(std::string s) : data(std::move(s)) {}
};
void demo() {
int a = 1, b = 2, c = 3;
process(a, b, c); // a unchanged, b incremented, c unchanged
std::string s = "hello";
Sink x{s}; // copies s
Sink y{std::move(s)}; // moves from s (s is valid but unspecified content)
}
Default Parameters
Default arguments are used when a call omits trailing arguments. They are evaluated at the call site and must appear on a declaration (typically in a header).
Only trailing parameters can have defaults; once a parameter has a default, all following parameters must also have defaults.
// Declarations with defaults (header)
void log(const char* msg, int level = 1, bool newline = true);
// Definition (source) — do NOT repeat defaults
void log(const char* msg, int level, bool newline) {
// ...
}
void use() {
log("hi"); // uses level=1, newline=true
log("warn", 2); // newline defaults to true
}
Templates & Terminology
The same distinction exists for templates: **template parameters** (in the template definition) vs **template arguments** (supplied at instantiation).
Example: in `template
// Template parameter vs argument
#include <vector>
template<class T>
void addOne(std::vector<T>& v, const T& x) { v.push_back(x + 1); }
void g() {
std::vector<int> vi;
addOne<int>(vi, 41); // template argument: int; function argument: 41
}
Common Pitfalls & Notes
Top-level `const` on by-value parameters does not affect the function signature (`void f(int)` and `void f(const int)` are the same signature).
Arrays passed to functions typically decay to pointers; consider `std::span
Do not rely on the relative **evaluation order** of function arguments—it's unspecified; avoid side effects that depend on a particular order.
Prefer clear const-correctness on references/pointers in parameter lists.
Real-World Analogy
Think of parameters like an order form (what information is needed) and arguments like the actual order details you fill in. The form structure stays the same, but the specific details change with each order.