Skip to content

C++ Functions

A function is a named block of code designed to perform a specific task. Functions are fundamental building blocks in C++ for organizing code, promoting reusability, and improving modularity. Every C++ program must contain a main function, which serves as the program’s entry point.

Breaking down complex problems into smaller, manageable functions makes code easier to write, test, debug, and maintain.

Key components of a function:

  • Function Declaration (Prototype): Tells the compiler about the function’s name, return type, and the types of its parameters. Allows the function to be called before its definition appears.
  • Function Definition: Provides the actual implementation (the code block) of the function.
  • Function Call (Invocation): Executes the code within the function definition.

The C++ Standard Library itself provides a vast collection of pre-defined functions (e.g., std::cout, std::sqrt, std::sort, std::string::length).

The general syntax for a function definition is:

return_type function_name(parameter_list) {
// Body of the function: statements that perform the task
// ...
return return_value; // Optional: only if return_type is not void
}

Components explained:

  • return_type: The data type of the value the function sends back to the caller. Use void if the function doesn’t return a value.
  • function_name: The identifier used to call the function.
  • parameter_list: A comma-separated list of parameter declarations (type and name) enclosed in parentheses (). These act as local variables within the function, receiving values (arguments) from the caller. If a function takes no parameters, the list is empty (()).
  • Function Body: The block of code ({ ... }) containing the statements that implement the function’s logic.
  • return Statement: Used to send a value back to the caller. The type of return_value must be compatible with return_type. A function with a void return type doesn’t need a return statement, or can use return; to exit early.

Here’s the definition of a function findMax that takes two integers and returns the larger one:

// Function definition for findMax
int findMax(int num1, int num2) { // return_type: int, name: findMax, parameters: num1, num2
// Function body
int result;
if (num1 > num2) {
result = num1;
} else {
result = num2;
}
return result; // Return the calculated maximum value
}

A function declaration, or prototype, introduces a function to the compiler before its definition appears in the code. This allows you to call the function earlier in the file or from different files (using header files).

The syntax is similar to the function header, followed by a semicolon:

return_type function_name(parameter_type_list);

Parameter names are optional in the declaration, but their types are mandatory.

// Function declaration (prototype) for findMax
int findMax(int num1, int num2); // Names included (optional, good for clarity)
// Or, equivalently:
int findMax(int, int); // Names omitted

Declarations are often placed in header files (.h or .hpp) to be included in multiple source files.

To use a function, you call (or invoke) it by using its name followed by parentheses (), providing the required arguments inside the parentheses.

When a function is called:

  • Control transfers from the calling code to the function’s body.
  • The provided arguments are used to initialize the function’s parameters.
  • The statements in the function body execute.
  • If a return statement is encountered (and the function isn’t void), the specified value is sent back to the caller, and control returns to the point immediately after the function call.
  • If the end of the function body is reached without a return (for non-void functions, this is often an error or leads to undefined behavior; for void functions, it’s normal), control returns to the caller.

Example: Declaring, Defining, and Calling a Function

#include <iostream>
// 1. Function Declaration (Prototype)
int findMax(int num1, int num2);
int main() {
// Local variables in main
int value1 = 100;
int value2 = 200;
int maximumValue;
// 3. Calling the function
// Arguments 'value1' and 'value2' are passed
maximumValue = findMax(value1, value2);
std::cout << "Max value is: " << maximumValue << std::endl;
// Call again with different arguments
std::cout << "Max of -5 and 10 is: " << findMax(-5, 10) << std::endl;
return 0;
}
// 2. Function Definition
int findMax(int num1, int num2) {
// Parameters 'num1' and 'num2' receive the argument values
int result;
if (num1 > num2) {
result = num1;
} else {
result = num2;
}
return result;
}

Output of the program:

Max value is: 200
Max of -5 and 10 is: 10

Parameters: Variables listed in the function definition’s parentheses (e.g., num1, num2 in findMax). They act as local variables within the function.

Arguments: The actual values or expressions passed to the function when it is called (e.g., value1, value2, -5, 10 in the calls to findMax).

C++ supports different ways to pass arguments:

Passing MethodDescriptionConceptual Example
Pass by ValueA copy of the argument’s value is passed to the function parameter. Changes made to the parameter inside the function do not affect the original argument outside the function. This is the default for fundamental types and objects unless otherwise specified.void func(int x) { x = 10; } int main() { int y = 5; func(y); // y remains 5 }
Pass by PointerThe memory address of the argument is passed (as a pointer). The function can use the pointer to access and modify the original argument’s value. Requires careful handling to avoid null pointer issues.void func(int* p) { *p = 10; } int main() { int y = 5; func(&y); // y becomes 10 }
Pass by ReferenceAn alias (reference) to the original argument is passed. The parameter becomes another name for the original argument. Changes made to the parameter do affect the original argument. Often preferred over pointers for modifying arguments as syntax is cleaner and null is not a possibility (references must be initialized).void func(int& r) { r = 10; } int main() { int y = 5; func(y); // y becomes 10 }
Pass by Constant ReferenceAn alias (reference) to the original argument is passed, but the function is prohibited from modifying it via the reference (const). This is the preferred way to pass large objects efficiently (avoids copying) when the function only needs to read them.void func(const std::string& s) { std::cout << s; /* s = "No!"; // Error! */ }

Choose the passing method based on whether you need to modify the original argument and the cost of copying (pass large objects by reference or const reference).

You can provide default values for parameters in the function declaration (or definition, but not both if separate). Default values must be specified for trailing parameters (parameters at the end of the list).

If a caller omits an argument for a parameter with a default value, the compiler uses the default. If the caller provides an argument, the provided value overrides the default.

#include <iostream>
// Function declaration with default value for 'b'
int sum(int a, int b = 20);
int main() {
int x = 100;
int y = 200;
int total;
// Calling with both arguments: default for 'b' is ignored
total = sum(x, y); // a=100, b=200
std::cout << "Total value (sum(100, 200)): " << total << std::endl;
// Calling with only one argument: default value for 'b' is used
total = sum(x); // a=100, b=20 (default)
std::cout << "Total value (sum(100)): " << total << std::endl;
return 0;
}
// Function definition
// (Default value should NOT be repeated here if declared in prototype)
int sum(int a, int b /* = 20 */) {
return a + b;
}

Output:

Total value (sum(100, 200)): 300
Total value (sum(100)): 120