What are value-returning functions?

A value-returning function is a function that computes a value and returns it to the caller. These functions have a return type other than void and must include a return statement that provides a value of that type.

return_type function_name(parameters)
{
    // compute something
    return value; // value must match return_type
}

The return statement

The return statement serves two purposes:

  1. It immediately exits the function
  2. It sends a value back to the caller
#include <iostream>

int multiply(int x, int y)
{
    int result = x * y;
    return result; // Returns the computed value
    
    // Any code after return is never executed
    std::cout << "This will never print\n";
}

int main()
{
    int answer = multiply(3, 4);
    std::cout << "3 * 4 = " << answer << std::endl;
    
    return 0;
}

Output:

3 * 4 = 12

Return types

Functions can return any valid C++ type.

Returning integers

int getAge()
{
    return 25;
}

int calculateSum(int a, int b)
{
    return a + b;
}

Returning floating-point numbers

double calculateCircleArea(double radius)
{
     double PI = 3.14159;
    return PI * radius * radius;
}

double divideNumbers(double numerator, double denominator)
{
    return numerator / denominator;
}

Returning characters

char getGrade(int score)
{
    if (score >= 90)
        return 'A';
    else if (score >= 80)
        return 'B';
    else if (score >= 70)
        return 'C';
    else if (score >= 60)
        return 'D';
    else
        return 'F';
}

Returning boolean values

bool isEven(int number)
{
    return (number % 2 == 0);
}

bool isValidPassword(int length)
{
    return length >= 8;
}

Using return values

You can use the return value in several ways:

1. Assign to a variable

#include <iostream>

double calculateTip(double bill, double tipPercent)
{
    return bill * (tipPercent / 100.0);
}

int main()
{
    double bill = 50.0;
    // This variable (tip) is storing the return of calculateTip
    double tip = calculateTip(bill, 15.0);
    
    std::cout << "Bill: $" << bill << std::endl;
    std::cout << "Tip: $" << tip << std::endl;
    std::cout << "Total: $" << (bill + tip) << std::endl;
    
    return 0;
}

2. Use directly in expressions

#include <iostream>

int square(int x)
{
    return x * x;
}

int main()
{
    // Use return value directly in calculations
    int result = square(5) + square(3);
    std::cout << "5² + 3² = " << result << std::endl;
    
    // Use return value in conditions
    if (square(4) > 10)
    {
        std::cout << "4² is greater than 10\n";
    }
    
    return 0;
}

Output:

5² + 3² = 34
4² is greater than 10

3. Chain function calls

#include <iostream>

double addTen(double x)
{
    return x + 10;
}

double multiplyByTwo(double x)
{
    return x * 2;
}

int main()
{
    double value = 5.0;

    // Chain function calls - first add 10, then multiply by 2
    double result = multiplyByTwo(addTen(value));

    std::cout << "multiplyByTwo(addTen(" << value << ")) = " << result << std::endl;
    // Output: multiplyByTwo(addTen(5)) = 30

    return 0;
}

Output:

multiplyByTwo(addTen(5)) = 30

Multiple return statements

A function can have multiple return statements, but only one will execute. This is because return does two things: it sends a value back to the caller AND immediately exits the function, so any code after a return won't run:

#include <iostream>

int getMax(int a, int b)
{
    if (a > b)
        return a;  // Returns immediately if a is larger
    else
        return b;  // Returns immediately if b is larger or equal
}

int main()
{
    std::cout << "Max of 10 and 7: " << getMax(10, 7) << std::endl;
    
    return 0;
}

Output:

Max of 10 and 7: 10

Early returns for efficiency

You can use return statements to exit a function early:

#include <iostream>

int divide(int a, int b)
{
    // Divide by zero
    if (b == 0)
        return -1;  // Early return for invalid input

    return a / b;   // Normal calculation
}

int main()
{
    std::cout << "10 / 2 = " << divide(10, 2) << std::endl;
    std::cout << "10 / 0 = " << divide(10, 0) << std::endl;

    return 0;
}

Best Practices

All code paths return a value

int goodFunction(int x)
{
    if (x > 0)
        return x;
    else
        return 0;  // Handle all cases
}

Meaningful return values

// Good: Clear what the function returns
double calculateInterest(double principal, double rate, int years)
{
    return principal * rate * years / 100.0;
}

// If necessary: Document with comments
/**
 * Calculates simple interest
 * @param principal The initial amount
 * @param rate Annual interest rate (as percentage)
 * @param years Number of years
 * @return The total interest earned
 */
double calculateSimpleInterest(double principal, double rate, int years)
{
    return principal * rate * years / 100.0;
}

Common mistakes

Missing return statement

int badFunction(int x)
{
    if (x > 0)
        return x;
    // Missing return for x <= 0 case!
    // This will cause undefined behavior
}

Unreachable code after return

int wastefulFunction(int x)
{
    return x * 2;
    
    // This code will never execute
    std::cout << "This is unreachable!\n";
    int unused = x + 1;
}

DRY Principle: Don't Repeat Yourself

An important programming principles is DRY (Don't Repeat Yourself). Functions are the primary tool for following this principle in C++.

Without functions (WET - Write Everything Twice):

#include <iostream>

int main()
{
    // Calculate tax for first purchase
    double price1 = 100.0;
    double tax1 = price1 * 0.08;  // 8% tax rate
    double total1 = price1 + tax1;
    std::cout << "Total for first purchase: $" << total1 << std::endl;

    // Calculate tax for second purchase - REPEATED CODE!
    double price2 = 250.0;
    double tax2 = price2 * 0.08;  // Same tax calculation repeated
    double total2 = price2 + tax2;
    std::cout << "Total for second purchase: $" << total2 << std::endl;

    // Calculate tax for third purchase - REPEATED AGAIN!
    double price3 = 75.0;
    double tax3 = price3 * 0.08;  // Same tax calculation repeated
    double total3 = price3 + tax3;
    std::cout << "Total for third purchase: $" << total3 << std::endl;

    return 0;
}

With functions (DRY approach):

#include <iostream>

double calculateTotal(double price)
{
    double tax = price * 0.08;  // Tax calculation in ONE place
    return price + tax;
}

int main()
{
    // Same logic, no repetition!
    std::cout << "Total for first purchase: $" << calculateTotal(100.0) << std::endl;
    std::cout << "Total for second purchase: $" << calculateTotal(250.0) << std::endl;
    std::cout << "Total for third purchase: $" << calculateTotal(75.0) << std::endl;

    return 0;
}

Benefits of following DRY:

  • Easier maintenance: Change tax rate in one place, not three
  • Less bugs: No risk of forgetting to update one copy
  • Cleaner code: Focus on what's different, not what's the same
  • Better testing: Test the function once, use everywhere

Void functions vs. value-returning functions

Void Functions Value-Returning Functions
Return type: void Return type: int, double, etc.
Don't return a value Return a value
Called as statements Called in expressions
Good for actions/output Good for calculations
Often create side effects Typically avoid side effects

Example of how to use the different function types

#include <iostream>

// Void function - output as a side effect
void displayResult(int result)
{
    std::cout << "The answer is: " << result << std::endl;
}

// Value-returning function - calculates and returns
int multiplyNumbers(int a, int b)
{
    return a * b;
}

int main()
{
    // Call value-returning function and use result
    int result = multiplyNumbers(6, 7);

    // Call void function to display result
    displayResult(result);

    // Or combine them:
    displayResult(multiplyNumbers(3, 4));

    return 0;
}

Output:

The answer is: 42
The answer is: 12

Summary

Value-returning functions are essential for creating modular, reusable code. Key points to remember:

  • Use return statement to send a value back to the caller
  • The return type must match the type of the returned value
  • Functions can have multiple return statements
  • All code paths in a value-returning function should return a value
  • Follow the DRY principle to avoid code repetition
  • Return statements immediately exit the function
  • Use meaningful return types and consider precision requirements