Lesson 4
Mastering Parameters - Default Values and References
Lesson Introduction

In this lesson, we'll dive into function parameters in C++, focusing on default values and references. These concepts help you write more flexible and efficient functions. By the end, you'll know how to set default values for parameters and modify variables directly by passing them by reference.

Default Values in Function Parameters

In C++, you can give function parameters default values. If you don't provide a value when calling the function, the default is used.

Imagine a function that prints a message. Sometimes, you might want to use a default message if none is provided:

C++
1#include <iostream> 2 3void displayMessage(std::string message = "Hello, World!") { 4 std::cout << message << std::endl; 5} 6 7int main() { 8 displayMessage(); // Outputs: Hello, World! 9 displayMessage("Hi there!"); // Outputs: Hi there! 10 return 0; 11}

Here, displayMessage has a default value of "Hello, World!" for its message parameter. When displayMessage is called without an argument, it prints the default message. With an argument like "Hi there!", it prints that instead.

Default values make functions flexible, reducing the need for additional function variants.

Potential Pitfalls

In C++, parameters with default values must be defined after any parameters without default values. This is important to ensure the function calls are unambiguous.

Here is an incorrectly defined function with a parameter with a default value appearing before a parameter without a default value:

C++
1#include <iostream> 2 3// This will cause a compilation error 4void printDetails(std::string country = "Unknown", std::string name, int age) { 5 std::cout << "Name: " << name << ", Age: " << age << ", Country: " << country << std::endl; 6} 7 8int main() { 9 // Compilation will fail 10 printDetails("USA", "Alice", 30); 11 return 0; 12}

In the incorrect example, the compiler will produce an error because it cannot determine how to handle the default parameter if it precedes non-default parameters.

Ensuring that parameters with default values are positioned after any non-default parameters allows the calls to the function to be clear and prevents any ambiguity for the compiler.

Here is a corrected version where the parameter with a default value comes after parameters without defaults:

C++
1#include <iostream> 2 3void printDetails(std::string name, int age, std::string country = "Unknown") { 4 std::cout << "Name: " << name << ", Age: " << age << ", Country: " << country << std::endl; 5} 6 7int main() { 8 printDetails("Alice", 30); // Outputs: Name: Alice, Age: 30, Country: Unknown 9 printDetails("Bob", 25, "USA"); // Outputs: Name: Bob, Age: 25, Country: USA 10 return 0; 11}
References in Function Parameters

References let you pass parameters by reference, meaning the function works with the original variable, not a copy. This allows the function to directly modify the original variable’s value.

Consider a function that increases a number by one:

C++
1#include <iostream> 2 3void increment(int &value) { 4 value++; 5} 6 7int main() { 8 int num = 10; 9 increment(num); 10 std::cout << num << std::endl; // Outputs: 11 11 return 0; 12}

Here, increment takes an int parameter by reference, shown by the & symbol before value. When you call increment(num), the actual value of num is incremented, not just a copy.

Now, let's see the difference when the function receives without reference:

C++
1#include <iostream> 2 3void incrementCopy(int value) { 4 value++; 5} 6 7int main() { 8 int num = 10; 9 incrementCopy(num); 10 std::cout << num << std::endl; // Outputs: 10 11 return 0; 12}

In this case, incrementCopy takes an int parameter by value, so the passed variable num is not modified.

Passing by reference is useful when you need to modify the original value. It’s like sharing a toy with a friend instead of giving them a duplicate; any changes affect the original toy.

Boosting Efficiency with References

In addition to allowing functions to modify original variables, passing by reference can boost efficiency, especially with large data types like std::string. When you pass by reference, the function works with the original data rather than making a copy, saving memory and processing time.

You can use a' const' reference to prevent the function from modifying the original data when it doesn't need to. This ensures that the data is not accidentally changed while still gaining the efficiency benefits.

Here's an example:

C++
1#include <iostream> 2 3void printGreeting(const std::string &name) { 4 std::cout << "Hello, " << name << "!" << std::endl; 5} 6 7int main() { 8 std::string userName = "Alice"; 9 printGreeting(userName); // Outputs: Hello, Alice! 10 return 0; 11}

In this example, printGreeting takes a const reference to a string. The const keyword ensures that name cannot be modified within the function. Passing by const reference avoids the overhead of copying the string while guaranteeing that the original string remains unchanged.

Using const references is particularly important when dealing with large objects or when you want to protect the data from being modified. It's like showing someone a book without letting them make any changes to its pages.

Lesson Summary

In this lesson, we covered:

  1. Using default values in function parameters to make functions flexible.
  2. Passing parameters by reference to directly modify variable values.

Understanding these concepts helps you write versatile and efficient functions in C++.

It's time to put these concepts into practice. The upcoming exercises will help you apply what you've learned about default values and references. Enjoy coding!

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.