Functions

Functions

#include <cmath>  // to get sqrt

double dist(double x1, double y1, double x2, double y2) {
    double dx = x1 - x2;
    double dy = y1 - y2;
    return sqrt(dx * dx + dy * dy);
}

this function is named dist

it returns a double

it takes four double parameters as input

Functions

double dist(double x1, double y1, double x2, double y2) // header
{
    double dx = x1 - x2;
    double dy = y1 - y2;                                // body
    return sqrt(dx * dx + dy * dy);
}

the first line of the function is the header (sometimes called the function’s signature)

the header has a lot of useful information

Functions

// declaration of a function: just a header, no body
double dist(double x1, double y1, double x2, double y2);

// definition of a function: header and body
double dist(double x1, double y1, double x2, double y2) // header
{
    double dx = x1 - x2;
    double dy = y1 - y2;                                // body
    return sqrt(dx * dx + dy * dy);
}

the header is the interface to the function

the body is the implementation of a function

generally, calling code only needs to know the header (the interface) to be able to use a function — it does not need to know the implementation

Functions

double dist(double x1, double y1, double x2, double y2) {
    double dx = x1 - x2;
    double dy = y1 - y2;
    return sqrt(dx * dx + dy * dy);
}

dx and dy are local variables visible only inside dist

x1, y1, x2, y2 are also local to dist

they are automatically de-allocated when the function ends

Functions

double dist(double x1, double y1, double x2, double y2) {
    double dx = x1 - x2;
    double dy = y1 - y2;
    return sqrt(dx * dx + dy * dy);
}

non-void functions must return a value

you can replace any double with a call to dist(), since it returns a double

Calling a Function

double dist(double x1, double y1, double x2, double y2) {
    double dx = x1 - x2;
    double dy = y1 - y2;
    return sqrt(dx * dx + dy * dy);
}

// ...

double x = dist(1, 2, 3, 4);

the order of the arguments must match the order of the parameters in the function header

Parameter Passing

void set_to_zero(double x) {
    x = 0.0; // our g++ settings signal an error here
}            // because x is set but never used

double x = 3.14;
set_to_zero(x);
cout << x;   // 3.14, x has not changed

C++ ordinarily passes parameters by value, i.e. it makes a copy of the passed-in parameter

pass by value means you can’t modify the actual parameter

Parameter Passing

void print(vector<string> v) {
    for(auto s : v) {
        cout << s << endl;
    }
}

v is passed by value, which means a copy of v is made

this could be slow and waste memory if v is big

Pass by Reference

void set_to_zero(double& x) {
    x = 0.0;
}

double x = 3.14;
set_to_zero(x);
cout << x; // 0, x has changed

double& means that x in the set_to_zero header is a reference to the x in the calling code

no copy is made

so x really is changed

Pass by Reference

void print(vector<string>& v) {
    for(auto s : v) {
        cout << s << endl;
    }
}

vector<string>& means v is passed by reference, so the vector is not copied

much better, but perhaps a safety concern

what if print modifies v

Pass by Constant Reference

void print(const vector<string>& v) {
    for(auto s : v) {
        cout << s << endl;
    }
}

vector<string>& means v is passed by constant reference, so the vector is not copied, and the compiler does not allow the body of the function to modify v

passing by constant reference is fast and safe

Advice

pass by value is usually fine for basic numeric types

use pass by constant reference in other cases when you can

use (non-constant) pass by reference when you need to modify a passed-in variable

Overloaded Functions

void print() { /* ... */ }

void print(string s) { /* ... */ }

void print(char c) { /* ... */ }

void print(long long n) { /* ... */ }

void print(const vector<double>& v) { /* ... */ }

functions can have the same name if they have different parameter types

see textbook for (many) more details

Overloaded Functions

anothe example of function overloading

double dist(double x1, double y1, double x2, double y2) {
    double dx = x1 - x2;
    double dy = y1 - y2;
    return sqrt(dx * dx + dy * dy);
}

struct Point {
    double x;
    double y;
};

double dist(const Point& a, const Point& b) {
    return dist(a.x, a.y, b.x, b.y);
}

int main() {
    double a = 1;
    double b = 2;
    double c = 3;
    double d = 4;

    cout << dist(a, b, c, d) << endl;

    Point p{a, b};
    Point q{c, d};

    cout << dist(p, q) << endl;

} // main