cpp

parameters

01_parameters.cpp⚙️
/**
 * ============================================================
 * C++ FUNCTION PARAMETERS
 * ============================================================
 * 
 * This file covers:
 * - Pass by value
 * - Pass by reference
 * - Pass by pointer
 * - Const parameters
 * - Array parameters
 * - Default arguments
 * 
 * Compile: g++ -std=c++17 -Wall 01_parameters.cpp -o parameters
 * Run: ./parameters
 * 
 * ============================================================
 */

#include <iostream>
#include <vector>
#include <string>

using namespace std;

// ============================================================
// FUNCTION DECLARATIONS
// ============================================================

// Pass by value
void incrementByValue(int x);

// Pass by reference
void incrementByReference(int& x);
void swap(int& a, int& b);

// Pass by pointer
void incrementByPointer(int* x);
void setToZero(int* ptr);

// Const parameters
void printValue(const int& x);
void printString(const string& str);
int sumArray(const int arr[], int size);
void displayVector(const vector<int>& vec);

// Array parameters
void fillArray(int arr[], int size, int value);
void printArray(int arr[], int size);
void modifyArray(int* arr, int size);

// Default arguments
void greet(string name = "Guest");
void printRectangle(int width, int height, char ch = '*');
int power(int base, int exp = 2);

// ============================================================
// MAIN FUNCTION
// ============================================================

int main() {
    cout << "============================================" << endl;
    cout << "     C++ FUNCTION PARAMETERS" << endl;
    cout << "============================================" << endl << endl;

    // ========================================================
    // PART 1: PASS BY VALUE
    // ========================================================
    
    cout << "--- PART 1: PASS BY VALUE ---" << endl << endl;
    
    /*
     * Pass by value: A COPY of the argument is passed
     * - Original variable is NOT modified
     * - Safe, but copies large objects
     */
    
    int num = 10;
    cout << "Before incrementByValue: num = " << num << endl;
    incrementByValue(num);
    cout << "After incrementByValue: num = " << num << " (unchanged!)" << endl;
    
    // Pass by value creates a copy
    // Good for: small types (int, char, etc.), when you don't want to modify original
    
    cout << endl;

    // ========================================================
    // PART 2: PASS BY REFERENCE
    // ========================================================
    
    cout << "--- PART 2: PASS BY REFERENCE ---" << endl << endl;
    
    /*
     * Pass by reference: The actual variable is passed (via alias)
     * - Original variable CAN be modified
     * - No copying - efficient for large objects
     * - Syntax: use & after the type
     */
    
    int value = 10;
    cout << "Before incrementByReference: value = " << value << endl;
    incrementByReference(value);
    cout << "After incrementByReference: value = " << value << " (modified!)" << endl;
    
    // Swap example
    int a = 5, b = 10;
    cout << "\nBefore swap: a=" << a << ", b=" << b << endl;
    swap(a, b);
    cout << "After swap: a=" << a << ", b=" << b << endl;
    
    cout << endl;

    // ========================================================
    // PART 3: PASS BY POINTER
    // ========================================================
    
    cout << "--- PART 3: PASS BY POINTER ---" << endl << endl;
    
    /*
     * Pass by pointer: Address of variable is passed
     * - Original variable CAN be modified (via dereference)
     * - Can be nullptr (handle null checks!)
     * - Syntax: use * after the type, pass &variable
     */
    
    int x = 10;
    cout << "Before incrementByPointer: x = " << x << endl;
    incrementByPointer(&x);  // Pass address using &
    cout << "After incrementByPointer: x = " << x << " (modified!)" << endl;
    
    // Pointer can be null
    int y = 100;
    setToZero(&y);
    cout << "After setToZero: y = " << y << endl;
    
    setToZero(nullptr);  // Safe - function checks for null
    
    cout << endl;

    // ========================================================
    // PART 4: CONST PARAMETERS
    // ========================================================
    
    cout << "--- PART 4: CONST PARAMETERS ---" << endl << endl;
    
    /*
     * Const reference: Pass by reference but prevent modification
     * - Efficient (no copy)
     * - Safe (can't modify)
     * - Best of both worlds!
     */
    
    int number = 42;
    printValue(number);  // Can pass variable
    printValue(100);     // Can pass literal (const ref allows this!)
    
    string longString = "This is a very long string that we don't want to copy";
    printString(longString);
    
    // Const with arrays
    int arr[] = {1, 2, 3, 4, 5};
    int sum = sumArray(arr, 5);
    cout << "Sum of array: " << sum << endl;
    
    // Const with vectors
    vector<int> vec = {10, 20, 30, 40, 50};
    displayVector(vec);
    
    cout << endl;

    // ========================================================
    // PART 5: ARRAY PARAMETERS
    // ========================================================
    
    cout << "--- PART 5: ARRAY PARAMETERS ---" << endl << endl;
    
    /*
     * Arrays decay to pointers when passed to functions
     * - int arr[] is same as int* arr
     * - Size must be passed separately
     * - Original array CAN be modified
     */
    
    int myArray[5];
    fillArray(myArray, 5, 42);
    cout << "After fillArray: ";
    printArray(myArray, 5);
    
    modifyArray(myArray, 5);
    cout << "After modifyArray: ";
    printArray(myArray, 5);
    
    cout << endl;

    // ========================================================
    // PART 6: DEFAULT ARGUMENTS
    // ========================================================
    
    cout << "--- PART 6: DEFAULT ARGUMENTS ---" << endl << endl;
    
    /*
     * Default arguments: Values used when argument is not provided
     * - Declared in function declaration (not definition)
     * - Must be at the END of parameter list
     * - Once you have a default, all following must have defaults
     */
    
    greet();            // Uses default "Guest"
    greet("Alice");     // Uses provided argument
    
    cout << endl;
    
    printRectangle(5, 3);       // Uses default '*'
    cout << endl;
    printRectangle(5, 3, '#');  // Uses provided '#'
    
    cout << endl;
    
    cout << "power(3): " << power(3) << " (uses default exp=2)" << endl;
    cout << "power(2, 8): " << power(2, 8) << " (explicit exp=8)" << endl;
    
    cout << endl;

    // ========================================================
    // PART 7: COMPARISON SUMMARY
    // ========================================================
    
    cout << "--- PART 7: COMPARISON ---" << endl << endl;
    
    cout << "┌──────────────────┬─────────────┬─────────────┬─────────────┐" << endl;
    cout << "│ Feature          │ By Value    │ By Reference│ By Pointer  │" << endl;
    cout << "├──────────────────┼─────────────┼─────────────┼─────────────┤" << endl;
    cout << "│ Modifies orig    │ No          │ Yes         │ Yes         │" << endl;
    cout << "│ Copies data      │ Yes         │ No          │ No          │" << endl;
    cout << "│ Can be null      │ N/A         │ No          │ Yes         │" << endl;
    cout << "│ Syntax (call)    │ func(x)     │ func(x)     │ func(&x)    │" << endl;
    cout << "│ Syntax (param)   │ int x       │ int& x      │ int* x      │" << endl;
    cout << "└──────────────────┴─────────────┴─────────────┴─────────────┘" << endl;
    
    cout << "\n💡 Best Practices:" << endl;
    cout << "• Small types (int, char): pass by value" << endl;
    cout << "• Large objects (read-only): pass by const reference" << endl;
    cout << "• Need to modify: pass by reference" << endl;
    cout << "• Optional/nullable: pass by pointer" << endl;
    
    cout << endl;

    cout << "============================================" << endl;
    cout << "PARAMETER PASSING SUMMARY:" << endl;
    cout << "============================================" << endl;
    cout << "• By value: copies, original unchanged" << endl;
    cout << "• By reference: no copy, can modify" << endl;
    cout << "• By pointer: uses address, can be null" << endl;
    cout << "• Use const& for read-only efficiency" << endl;
    cout << "• Default args must be at end" << endl;
    cout << "============================================" << endl;

    return 0;
}

// ============================================================
// FUNCTION DEFINITIONS
// ============================================================

// Pass by value - receives a COPY
void incrementByValue(int x) {
    x++;  // Only modifies the local copy
    cout << "  Inside function: x = " << x << endl;
}

// Pass by reference - receives the ACTUAL variable
void incrementByReference(int& x) {
    x++;  // Modifies the original variable
}

// Swap using references
void swap(int& a, int& b) {
    int temp = a;
    a = b;
    b = temp;
}

// Pass by pointer
void incrementByPointer(int* x) {
    if (x != nullptr) {  // Always check for null!
        (*x)++;  // Dereference and increment
    }
}

void setToZero(int* ptr) {
    if (ptr != nullptr) {
        *ptr = 0;
    } else {
        cout << "Received null pointer - no action taken" << endl;
    }
}

// Const reference - efficient and safe
void printValue(const int& x) {
    cout << "Value: " << x << endl;
    // x = 10;  // ERROR: cannot modify const reference
}

void printString(const string& str) {
    cout << "String: " << str << endl;
    // str = "changed";  // ERROR: cannot modify const reference
}

// Const with array
int sumArray(const int arr[], int size) {
    int sum = 0;
    for (int i = 0; i < size; i++) {
        sum += arr[i];
        // arr[i] = 0;  // ERROR: cannot modify const array
    }
    return sum;
}

// Const with vector
void displayVector(const vector<int>& vec) {
    cout << "Vector: ";
    for (int val : vec) {
        cout << val << " ";
    }
    cout << endl;
}

// Array parameters (arrays decay to pointers)
void fillArray(int arr[], int size, int value) {
    for (int i = 0; i < size; i++) {
        arr[i] = value;
    }
}

void printArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        cout << arr[i] << " ";
    }
    cout << endl;
}

// Using pointer syntax explicitly
void modifyArray(int* arr, int size) {
    for (int i = 0; i < size; i++) {
        arr[i] *= 2;  // Double each element
    }
}

// Default arguments
void greet(string name) {  // Default value in declaration only!
    cout << "Hello, " << name << "!" << endl;
}

void printRectangle(int width, int height, char ch) {
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            cout << ch;
        }
        cout << endl;
    }
}

int power(int base, int exp) {
    int result = 1;
    for (int i = 0; i < exp; i++) {
        result *= base;
    }
    return result;
}

// ============================================================
// EXERCISES:
// ============================================================
/*
 * 1. Write a function that finds min and max of an array
 *    using reference parameters for the results
 * 
 * 2. Write a function that reverses a string in place
 *    using pass by reference
 * 
 * 3. Write a function with default arguments that calculates
 *    simple interest (principal, rate, time)
 * 
 * 4. Write a function that safely divides two numbers
 *    using pointers to return both quotient and remainder
 * 
 * 5. Write a function that modifies a vector to remove
 *    all negative numbers
 */
Parameters - C++ Tutorial | DeepML