पाठ 5 / 25

Functions and Parameter Passing

Pass arguments by value, reference and const reference, and use overloading and constexpr.

Choosing how to pass arguments

How you pass arguments affects both performance and correctness. By value (void f(int x)) copies the argument: ideal for small, cheap types such as int, double and small structs, and for parameters the function will keep a copy of anyway. By const reference (void f(const std::string& s)) avoids copying large objects while promising not to modify them: the default for read-only inputs of class type. By non-const reference (void f(std::vector<int>& v)) lets the function modify the caller's object: use it sparingly and make it obvious, because returning a value is usually clearer. By pointer is for optional arguments (nullptr meaning "none") or C interfaces. Return results by value: compilers apply copy elision and move semantics, so returning a std::vector is cheap. Functions can be overloaded by parameter types, have default arguments, and be marked constexpr so they can run at compile time when given constant inputs. Use [[nodiscard]] on functions whose return value must not be ignored.

Parameter passing in practice

Small types by value, large inputs by const reference, results returned by value.

#include <cctype>
#include <numeric>
#include <string>
#include <vector>

constexpr int square(int x) { return x * x; }          // can run at compile time
static_assert(square(12) == 144);

[[nodiscard]] double average(const std::vector<int>& values) {   // read-only, no copy
    if (values.empty()) return 0.0;
    return std::accumulate(values.begin(), values.end(), 0.0) / values.size();
}

void normalise(std::string& name) {                     // modifies the caller's string
    for (auto& ch : name) ch = static_cast<char>(std::tolower(static_cast<unsigned char>(ch)));
}

std::vector<int> evens_up_to(int n) {                   // return by value: cheap (move/elision)
    std::vector<int> out;
    for (int i = 0; i <= n; i += 2) out.push_back(i);
    return out;
}

std::string greet(const std::string& name, const std::string& greeting = "Hello") {
    return greeting + ", " + name;
}

Lending a book

Passing by value is handing someone a photocopy. Passing by const reference is lending the original with a "read only" sticker. Passing by non-const reference is lending it with permission to write in the margins, so make sure that is what you intend.

त्वरित जाँच: What is the usual way to pass a large std::vector that a function only reads?

  • By value
  • By const reference
  • By non-const reference
  • As a global variable
Answer

By const reference — const reference avoids copying while guaranteeing the function will not modify the argument.