Passing Parameter Packs by Value or Reference
When should I pass the parameters in a parameter pack by value, reference, const reference, or forwarding reference?
The choice of passing parameters by value, reference, const reference, or forwarding reference depends on your specific use case:
Pass by value when:
- The parameter is a small, cheap-to-copy type like int, double, bool, etc.
- You want to work with a copy of the argument and avoid modifying the original
Pass by reference (&
) when:
- The parameter is a large, expensive-to-copy type like a vector or string
- You need to modify the original argument and have those changes persist after the function call
Pass by const reference (const &
) when:
- The parameter is a large, expensive-to-copy type
- You don't need to modify the original argument
- You want to avoid the overhead of copying
Pass by forwarding reference (&&
) when:
- You need to forward the arguments to another function while preserving their value category (lvalue/rvalue)
- You want to avoid unnecessary copying and enable perfect forwarding
For example:
template <typename... Types>
void LogByValue(Types... Args) {
// Each arg copied into the function
(std::cout << ... << Args) << '\n';
}
template <typename... Types>
void LogByReference(Types&... Args) {
// Each arg passed by reference
(std::cout << ... << Args) << '\n';
Args...; // Potential to modify arguments
}
template <typename... Types>
void LogByConstRef(const Types&... Args) {
// Each arg passed by const reference
(std::cout << ... << Args) << '\n';
// Args...; // Can't modify arguments
}
template <typename... Types>
void LogAndForward(Types&&... Args) {
(std::cout << ... << Args) << '\n';
SomeOtherFunction(std::forward<Types>(Args)...);
}
In general, prefer passing by value for small types and const reference for large types. Use non-const references when you need to modify arguments, and forwarding references when you need to forward arguments while preserving their original value category.
Variadic Functions
An introduction to variadic functions, which allow us to pass a variable quantity of arguments