cpp

examples

examples.cpp⚙️
/**
 * Function Parameters in C++ - Comprehensive Examples
 * 
 * Demonstrates:
 * - Pass by value, reference, and pointer
 * - Const correctness
 * - Default arguments
 * - Array parameters
 * - Multiple return values via out parameters
 * 
 * Compile: g++ -std=c++17 -Wall -Wextra examples.cpp -o examples
 * Run: ./examples
 */

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

using namespace std;

// ============================================================
// SECTION 1: PASS BY VALUE
// ============================================================

/**
 * Pass by value - receives a copy.
 * Original value is NOT modified.
 */
void incrementByValue(int x) {
    x++;  // Only modifies local copy
    cout << "  Inside function: x = " << x << endl;
}

/**
 * Pass by value with string (expensive copy!)
 */
void printUpperByValue(string s) {
    for (char& c : s) {
        c = toupper(c);
    }
    cout << "  Inside: " << s << endl;
}

/**
 * When pass-by-value is appropriate
 */
int square(int n) {
    return n * n;  // Small type, no need for reference
}

double circleArea(double radius) {
    return 3.14159 * radius * radius;
}

// ============================================================
// SECTION 2: PASS BY REFERENCE
// ============================================================

/**
 * Pass by reference - modifies original.
 */
void incrementByRef(int& x) {
    x++;  // Modifies caller's variable
}

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

/**
 * Swap any type using templates
 */
template<typename T>
void swapGeneric(T& a, T& b) {
    T temp = a;
    a = b;
    b = temp;
}

/**
 * Modify string in place
 */
void toUppercase(string& s) {
    for (char& c : s) {
        c = toupper(c);
    }
}

/**
 * Clear and fill a vector
 */
void fillWithRange(vector<int>& v, int start, int end) {
    v.clear();
    for (int i = start; i <= end; i++) {
        v.push_back(i);
    }
}

// ============================================================
// SECTION 3: CONST REFERENCE (Read-Only, Efficient)
// ============================================================

/**
 * Const reference - read-only access, no copy
 */
void printVector(const vector<int>& v) {
    cout << "  [";
    for (size_t i = 0; i < v.size(); i++) {
        cout << v[i];
        if (i < v.size() - 1) cout << ", ";
    }
    cout << "]" << endl;
}

/**
 * Calculate sum without modifying or copying
 */
long long sum(const vector<int>& numbers) {
    long long total = 0;
    for (int n : numbers) {
        total += n;
    }
    return total;
}

/**
 * Find maximum in vector
 */
int findMax(const vector<int>& v) {
    if (v.empty()) return 0;
    int maxVal = v[0];
    for (int n : v) {
        if (n > maxVal) maxVal = n;
    }
    return maxVal;
}

/**
 * String analysis - const ref for efficiency
 */
int countVowels(const string& s) {
    int count = 0;
    for (char c : s) {
        c = tolower(c);
        if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
            count++;
        }
    }
    return count;
}

// ============================================================
// SECTION 4: PASS BY POINTER
// ============================================================

/**
 * Pointer parameter - can be nullptr
 */
void incrementByPtr(int* ptr) {
    if (ptr != nullptr) {
        (*ptr)++;
    }
}

/**
 * Optional output parameter
 */
bool safeDivide(int a, int b, double* result) {
    if (b == 0) {
        return false;
    }
    if (result != nullptr) {
        *result = static_cast<double>(a) / b;
    }
    return true;
}

/**
 * Multiple outputs via pointers
 */
void getMinMax(const vector<int>& v, int* outMin, int* outMax) {
    if (v.empty()) return;
    
    int minVal = v[0], maxVal = v[0];
    for (int n : v) {
        if (n < minVal) minVal = n;
        if (n > maxVal) maxVal = n;
    }
    
    if (outMin) *outMin = minVal;
    if (outMax) *outMax = maxVal;
}

/**
 * Search with optional index output
 */
bool findElement(const vector<int>& v, int target, int* outIndex) {
    for (size_t i = 0; i < v.size(); i++) {
        if (v[i] == target) {
            if (outIndex) *outIndex = static_cast<int>(i);
            return true;
        }
    }
    return false;
}

// ============================================================
// SECTION 5: CONST POINTER VARIATIONS
// ============================================================

/**
 * Pointer to const - can't modify data through pointer
 */
void printArray(const int* arr, int size) {
    for (int i = 0; i < size; i++) {
        cout << arr[i] << " ";
    }
    cout << endl;
}

/**
 * Const pointer - can't reassign the pointer itself
 */
void fillArray(int* const arr, int size, int value) {
    // arr = nullptr;  // ERROR: can't reassign const pointer
    for (int i = 0; i < size; i++) {
        arr[i] = value;  // OK: can modify data
    }
}

// ============================================================
// SECTION 6: DEFAULT ARGUMENTS
// ============================================================

/**
 * Simple default argument
 */
void greet(const string& name, const string& greeting = "Hello") {
    cout << greeting << ", " << name << "!" << endl;
}

/**
 * Multiple defaults
 */
void printMessage(const string& msg, 
                  int times = 1, 
                  const string& prefix = ">> ",
                  const string& suffix = "") {
    for (int i = 0; i < times; i++) {
        cout << prefix << msg << suffix << endl;
    }
}

/**
 * Power function with default exponent
 */
double power(double base, int exp = 2) {
    double result = 1.0;
    bool negative = exp < 0;
    exp = abs(exp);
    for (int i = 0; i < exp; i++) {
        result *= base;
    }
    return negative ? 1.0 / result : result;
}

/**
 * Format number with optional precision and prefix
 */
string formatNumber(double value, int precision = 2, const string& prefix = "") {
    string result = prefix;
    
    // Simple formatting (not production-quality)
    int wholePart = static_cast<int>(value);
    double fracPart = value - wholePart;
    
    result += to_string(wholePart) + ".";
    
    for (int i = 0; i < precision; i++) {
        fracPart *= 10;
        result += to_string(static_cast<int>(fracPart) % 10);
    }
    
    return result;
}

// ============================================================
// SECTION 7: ARRAY PARAMETERS
// ============================================================

/**
 * Array decays to pointer - size is NOT preserved
 */
void processArray(int arr[], int size) {
    // sizeof(arr) would give pointer size, not array size!
    for (int i = 0; i < size; i++) {
        arr[i] *= 2;
    }
}

/**
 * Safer: explicitly use pointer
 */
int arraySum(const int* arr, size_t size) {
    int total = 0;
    for (size_t i = 0; i < size; i++) {
        total += arr[i];
    }
    return total;
}

/**
 * Template: preserve array size
 */
template<size_t N>
void printFixedArray(const int (&arr)[N]) {
    cout << "  Array of size " << N << ": ";
    for (size_t i = 0; i < N; i++) {
        cout << arr[i] << " ";
    }
    cout << endl;
}

// ============================================================
// SECTION 8: MIXED PARAMETER TYPES
// ============================================================

/**
 * Complex function with multiple parameter types
 */
bool processData(const vector<int>& input,    // Read-only input
                 vector<int>& output,          // Output container
                 int* errorCount = nullptr,    // Optional error count
                 int threshold = 0) {          // Default threshold
    output.clear();
    int errors = 0;
    
    for (int val : input) {
        if (val >= threshold) {
            output.push_back(val);
        } else {
            errors++;
        }
    }
    
    if (errorCount) *errorCount = errors;
    return errors == 0;
}

/**
 * Configuration via struct (alternative to many parameters)
 */
struct PrintConfig {
    string prefix = "";
    string suffix = "";
    string separator = ", ";
    bool showIndices = false;
};

void printVectorConfigured(const vector<int>& v, const PrintConfig& config = {}) {
    cout << config.prefix;
    for (size_t i = 0; i < v.size(); i++) {
        if (config.showIndices) {
            cout << "[" << i << "]=";
        }
        cout << v[i];
        if (i < v.size() - 1) cout << config.separator;
    }
    cout << config.suffix << endl;
}

// ============================================================
// DEMONSTRATION FUNCTIONS
// ============================================================

void demonstratePassByValue() {
    cout << "\n╔══════════════════════════════════════════════════════════════╗" << endl;
    cout << "║              SECTION 1: Pass By Value                        ║" << endl;
    cout << "╚══════════════════════════════════════════════════════════════╝" << endl;
    
    int x = 10;
    cout << "Before incrementByValue: x = " << x << endl;
    incrementByValue(x);
    cout << "After incrementByValue: x = " << x << " (unchanged!)" << endl;
    
    cout << "\nSquare: " << square(5) << endl;
    cout << "Circle area (r=3): " << circleArea(3) << endl;
    
    string s = "hello";
    cout << "\nBefore printUpperByValue: s = " << s << endl;
    printUpperByValue(s);
    cout << "After printUpperByValue: s = " << s << " (unchanged!)" << endl;
}

void demonstratePassByReference() {
    cout << "\n╔══════════════════════════════════════════════════════════════╗" << endl;
    cout << "║              SECTION 2: Pass By Reference                    ║" << endl;
    cout << "╚══════════════════════════════════════════════════════════════╝" << endl;
    
    int x = 10;
    cout << "Before incrementByRef: x = " << x << endl;
    incrementByRef(x);
    cout << "After incrementByRef: x = " << x << " (modified!)" << endl;
    
    int a = 5, b = 10;
    cout << "\nBefore swap: a = " << a << ", b = " << b << endl;
    swap(a, b);
    cout << "After swap: a = " << a << ", b = " << b << endl;
    
    string s = "hello world";
    cout << "\nBefore toUppercase: s = " << s << endl;
    toUppercase(s);
    cout << "After toUppercase: s = " << s << endl;
    
    vector<int> v;
    fillWithRange(v, 1, 5);
    cout << "\nAfter fillWithRange(1, 5): ";
    printVector(v);
}

void demonstrateConstReference() {
    cout << "\n╔══════════════════════════════════════════════════════════════╗" << endl;
    cout << "║           SECTION 3: Const Reference (Efficient)             ║" << endl;
    cout << "╚══════════════════════════════════════════════════════════════╝" << endl;
    
    vector<int> numbers = {3, 1, 4, 1, 5, 9, 2, 6};
    
    cout << "Vector: ";
    printVector(numbers);
    cout << "Sum: " << sum(numbers) << endl;
    cout << "Max: " << findMax(numbers) << endl;
    
    string text = "Hello World";
    cout << "\nVowels in \"" << text << "\": " << countVowels(text) << endl;
}

void demonstratePassByPointer() {
    cout << "\n╔══════════════════════════════════════════════════════════════╗" << endl;
    cout << "║              SECTION 4: Pass By Pointer                      ║" << endl;
    cout << "╚══════════════════════════════════════════════════════════════╝" << endl;
    
    int x = 10;
    cout << "Before incrementByPtr: x = " << x << endl;
    incrementByPtr(&x);
    cout << "After incrementByPtr: x = " << x << endl;
    
    incrementByPtr(nullptr);  // Safe: checks for null
    cout << "incrementByPtr(nullptr): No crash!" << endl;
    
    double result;
    cout << "\nsafeDivide(10, 3): ";
    if (safeDivide(10, 3, &result)) {
        cout << result << endl;
    }
    
    cout << "safeDivide(10, 0): ";
    if (!safeDivide(10, 0, &result)) {
        cout << "Division by zero!" << endl;
    }
    
    // Just checking without needing result
    cout << "safeDivide(10, 2, nullptr): " 
         << (safeDivide(10, 2, nullptr) ? "OK" : "Failed") << endl;
    
    vector<int> v = {5, 2, 8, 1, 9, 3};
    int minVal, maxVal;
    getMinMax(v, &minVal, &maxVal);
    cout << "\nMin: " << minVal << ", Max: " << maxVal << endl;
    
    // Only get max
    getMinMax(v, nullptr, &maxVal);
    cout << "Max only: " << maxVal << endl;
    
    int idx;
    if (findElement(v, 8, &idx)) {
        cout << "Found 8 at index " << idx << endl;
    }
}

void demonstrateDefaultArguments() {
    cout << "\n╔══════════════════════════════════════════════════════════════╗" << endl;
    cout << "║              SECTION 5: Default Arguments                    ║" << endl;
    cout << "╚══════════════════════════════════════════════════════════════╝" << endl;
    
    greet("Alice");           // Uses default greeting
    greet("Bob", "Welcome");  // Custom greeting
    
    cout << "\nprintMessage with various defaults:" << endl;
    printMessage("Test");                    // All defaults
    printMessage("Test", 2);                 // Custom times
    printMessage("Test", 3, "## ");          // Custom prefix
    printMessage("Test", 1, "-> ", " <-");   // All custom
    
    cout << "\nPower function:" << endl;
    cout << "power(5) = " << power(5) << " (default: square)" << endl;
    cout << "power(2, 10) = " << power(2, 10) << endl;
    cout << "power(2, -3) = " << power(2, -3) << endl;
    
    cout << "\nNumber formatting:" << endl;
    cout << formatNumber(3.14159) << endl;
    cout << formatNumber(3.14159, 4) << endl;
    cout << formatNumber(99.5, 2, "$") << endl;
}

void demonstrateArrayParameters() {
    cout << "\n╔══════════════════════════════════════════════════════════════╗" << endl;
    cout << "║              SECTION 6: Array Parameters                     ║" << endl;
    cout << "╚══════════════════════════════════════════════════════════════╝" << endl;
    
    int arr[] = {1, 2, 3, 4, 5};
    int size = sizeof(arr) / sizeof(arr[0]);
    
    cout << "Original array: ";
    printArray(arr, size);
    
    processArray(arr, size);
    cout << "After doubling: ";
    printArray(arr, size);
    
    cout << "Sum: " << arraySum(arr, size) << endl;
    
    int fixed[] = {10, 20, 30};
    printFixedArray(fixed);  // Template preserves size
}

void demonstrateMixedParameters() {
    cout << "\n╔══════════════════════════════════════════════════════════════╗" << endl;
    cout << "║              SECTION 7: Mixed Parameter Types                ║" << endl;
    cout << "╚══════════════════════════════════════════════════════════════╝" << endl;
    
    vector<int> input = {5, -2, 10, -7, 3, 0, 8};
    vector<int> output;
    int errors;
    
    cout << "Input: ";
    printVector(input);
    
    bool success = processData(input, output, &errors, 0);
    cout << "Filtered (threshold=0): ";
    printVector(output);
    cout << "Errors: " << errors << ", Success: " << boolalpha << success << endl;
    
    cout << "\nConfigured printing:" << endl;
    printVectorConfigured(output);  // Default config
    
    PrintConfig cfg;
    cfg.prefix = "Data: [";
    cfg.suffix = "]";
    cfg.showIndices = true;
    printVectorConfigured(output, cfg);
}

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

int main() {
    cout << "╔════════════════════════════════════════════════════════════════════╗" << endl;
    cout << "║              C++ FUNCTION PARAMETERS EXAMPLES                      ║" << endl;
    cout << "║          Understanding Different Parameter Passing Methods         ║" << endl;
    cout << "╚════════════════════════════════════════════════════════════════════╝" << endl;
    
    demonstratePassByValue();
    demonstratePassByReference();
    demonstrateConstReference();
    demonstratePassByPointer();
    demonstrateDefaultArguments();
    demonstrateArrayParameters();
    demonstrateMixedParameters();
    
    cout << "\n╔════════════════════════════════════════════════════════════════════╗" << endl;
    cout << "║                       Examples Complete!                           ║" << endl;
    cout << "╚════════════════════════════════════════════════════════════════════╝" << endl;
    
    return 0;
}
Examples - C++ Tutorial | DeepML