News & UpdatesProgrammingWeb programmingStoreMy Projects
Links
Affiliates

C++ Tutorial – 14 – Functions II

Pass by value

In C++, variables of both primitive and object data types are by default passed by value. This means that only a copy of the value or object is passed to the function. Therefore, changing the parameter in any way will not affect the original, and passing a large object will be very slow.

#include <iostream>
#include <string>
using namespace std;
 
void set(int i)    { i = 10; } 
void set(string s) { s = "Hello World"; }
 
int main()
{
  int x = 0;     // value type
  set(x);        // value copy is passed
  cout << x;     // "0"
 
  string y = ""; // reference type
  set(y);        // object copy is passed
  cout << y;     // ""
}

Pass by reference

Alternatively, to instead pass a variable by reference you just need to add an ampersand before the parameter’s name in the function’s definition. When passing arguments by reference, both primitive and object data types can be changed or replaced and the changes will affect the original.

void set(int& i) { i = 10; }
 
int main()
{
  int x = 0; // value type
  set(x);    // reference is passed
  cout << x; // "10"
}

Pass by address

As an alternative to passing by reference, arguments may also be passed by address using pointers. This passing technique serves the same purpose as passing by reference, but uses pointer syntax instead.

void set(int* i) { *i = 10; }
 
int main()
{
  int x = 0;  // value type
  set(&x);    // address is passed
  cout << x;  // "10"
}

Return by value, reference or address

In addition to passing variables by value, reference or address, a variable may also be returned in one of these ways. Most commonly, a function returns by value, in which case a copy of the value is returned to the caller.

int byVal(int i) { return i + 1; }  
 
int main()
{
  int a = 10;
  cout << byVal(a); // "11"
}

To return by reference instead, an ampersand is placed after the function’s return type. The function must then return a variable and may not return an expression or literal, as can be done when using return by value. The variable returned should never be a local variable, since the memory to these variables is released when the function ends. Instead, return by reference is commonly used to return an argument that has also been passed to the function by reference.

int& byRef(int& i) { return i; } 
 
int main()
{
  int a = 10;
  cout << byRef(a); // "10"
}

To return by address the dereference operator is appended to the function’s return type. This return technique has the same two restrictions as when returning by reference – the address of a variable must be returned and that returned variable must not be local to the function.

int* byAdr(int* i) { return i; }
 
int main()
{
  int a = 10;
  cout << *byAdr(&a); // "10"
}

Inline functions

A thing to keep in mind when using functions is that every time a function is called, a performance overhead occurs. To potentially remove this overhead you can recommend that the compiler inlines the calls to a specific function by using the inline function modifier. This keyword is best suited for small functions that are called inside loops. It should not be used on larger functions since inlining these can severely increase the size of the code, which will instead decrease performance.

inline int myInc(int i) { return i++; }

Note that the inline keyword is only a recommendation. The compiler may in its attempts to optimize the code choose to ignore this recommendation and it may also inline functions that do not have the inline modifier.

Recommended additional reading:
Sams - Teach Yourself C++ in One Hour a Day