8. Technicalities: Functions, etc.
8.1 Technicalities

When you start programming, your programming language
is a foreign language for which you need to look at
“grammar and vocabulary”.
Most design and programming concepts are universal,
and many such concepts are widely supported by popular
programming languages.
That means that the fundamental ideas and techniques
we learn in a good programming course carry
over from language to language.
The language technicalities, however, are specific to a
given language. Fortunately, programming languages do not
develop in a vacuum, so much of what you learn here will
have reasonably obvious counterparts in other languages.
In particular, C++ belongs to a group of languages
that also includes C, Java, and C#,
so quite a few technicalities are shared with those
languages.
8.2 Declarations and definitions

A declaration is a statement that introduces a name into a scope:
- Specifying a type for what is named (e.g., a variable or a function)
- Optionally, specifying an initializer (e.g., an initializer value or a function body)
Example:
int a = 7; // an int variable
const double cd = 8.7; // a double-precision floating-point constant
double sqrt(double); // a function taking a double argument
// and returning a double result
vector<Token> v; // a vector-of-Tokens variable
Before a name can be used in a C++ program,
it must be declared.
Consider:
int main()
{
cout << f(i) << '\n';
}
The compiler will give at least three
“undeclared identifier” errors for this:
cout
, f
, and i
are not declared anywhere in this program fragment.
After Fixing:
#include "std_lib_facilities.h" // we find the declaration of cout in here
int f(int); // declaration of f
int main()
{
int i = 7; // declaration of i
cout << f(i) << '\n';
}
This will compile because every name has been declared,
but it will not link because we have not defined
f()
; that is, nowhere have we specified
what f()
actually does.
A definition specifies exactly what a name refers
to. In particular, a definition of a variable sets
aside memory for that variable.
Example:
int x = 7; // definition
double sqrt(double d) { /* . . . */ } // definition
8.2.1 Kinds of declarations
Following are the kind of entities that a programmer
can define in C++:
- Variables
- Constants
- Functions
- Namespaces
- Types (classes and enumerations)
- Templates
8.2.2 Variable and constant declarations

The declaration of a variable or a constant specifies
a name, a type, and optionally an initializer:
int a; // no initializer
double d = 7; // initializer using the = syntax
vector<int> vi(10); // initializer using the ( ) syntax
vector<int> vi2 {1,2,3,4}; // initializer using the { } syntax
Constants have the same declaration syntax as
variables. They differ in having const
as part of their type and requiring an initializer:
const int x = 7; // initializer using the = syntax
const int x2 {9}; // initializer using the {} syntax
8.2.3 Default initialization
vector<string> v;
string s;
while (cin>>s) v.push_back(s);
Here, string
and vector
are
defined so that variables of those types are
initialized with a default value whenever we don’t
supply one explicitly.
Thus, v
is empty (it has no elements)
and s
is the empty string
(""
) before we reach the loop.
The mechanism for guaranteeing
default initialization is called a
default constructor.
Unfortunately, the language doesn’t allow us to make such guarantees for built-in types.
8.3 Header files

As programs grow larger and larger
(and include more files), it becomes increasingly tedious
to have to forward declare every function you want to
use that lives in a different file.
Wouldn’t it be nice if you could put all your
declarations in one place?
Header files usually have a .h
extension, but you will sometimes see them with a
.hpp
extension or no extension at all.
The purpose of a header file is to hold declarations
for other files to use.
Drill
Separate out the tokenizing code from the rest of your
calculator program. Put your declarations in
token.h
and your definitions to
token.cpp
. Get this version to compile and
link.
8.4 Scope

Scope is a region of program text
with the main purpose to keep the extent of a
program code within which the variable can be accessed.
Kinds of scopes used to control where names
can be used are:
- Global scope: the area of text outside any other scope
- Namespace scope: a named scope nested in the global scope or in another namespace
- Class scope: the area of text within a class
- Local scope:
between
{ . . . }
braces of a block or in a function argument list - Statement scope:
e.g., in a
for
-statement
8.5 Function call and return


Functions are the way we represent actions and
computations.
In a programming language, a function is a type of
procedure or routine. Functions allow us to reuse code
instead of rewriting it.
They also help organize the code.
8.5.1 Declaring arguments and return type

A function can be declared in following way:
return_type function_name( parameter list );
A definition contains the function body
(the statements to be executed by a call),
whereas a declaration that isn’t a definition
just has a semicolon.
Formal arguments are often called parameters.
- If you don’t want a function to take arguments, just leave out the formal arguments.
-
If you don’t want to return a value
from a function, give
void
as its return type.
8.5.2 Returning a value
A return
type specifies
the type of the data value being returned by the
written function.
Also, function may or may not return a value.
The return type is void
if the function
does not return a value.
void print_until_s(vector<string> v, string quit)
{
for(int s : v) {
if (s==quit) return;
cout << s << '\n';
}
}
In code shown in 8.5.1
, the return value is an integer value
c
, which is int
.
8.5.3 Pass-by-value
The simplest way of passing an argument to a
function is to give the function a copy of the value
you use as the argument. An argument of a function
f()
is a local variable in
f()
that’s initialized each time
f()
is called.
Example:
// pass-by-value (give the function a copy of the value passed)
int f(int x)
{
x = x+1; // give the local x a new value
return x;
}
int main()
{
int xx = 0;
cout << f(xx) << '\n'; // write: 1
cout << xx << '\n'; // write: 0; f() doesn’t change xx
int yy = 7;
cout << f(yy) << '\n'; // write: 8
cout << yy << '\n'; // write: 7; f() doesn’t change yy
}
Graphical Representation:
8.5.4 Pass-by-const-reference
If a value is large, such as an image
(often, several million bits),
a large table of values (say, thousands of
integers), or a long string
(say, hundreds of characters)?
Then, Pass-by-value
can be costly.
Example:
void print(const vector<double>& v) // pass-by-const-reference
{
cout << "{ ";
for (int i = 0; i<v.size(); ++i) {
cout << v[i];
if (i!=v.size()–1) cout << ", ";
}
cout << " }\n";
}
void f(int x)
{
vector<double> vd1(10); // small vector
vector<double> vd2(1000000); // large vector
vector<double> vd3(x); // vector of some unknown size
// . . . fill vd1, vd2, vd3 with values . . .
print(vd1);
print(vd2);
print(vd3);
}
The above code shows a way of giving our
print()
function “the address” of the
vector to print()
rather than the
copy of the vector. Such an “address” is
called a reference.
The &
means “reference” and
the const is there to stop print()
modifying its argument by accident. Apart from
the change to the argument declaration, all is the
same as before; the only change is that
instead of operating on a copy, print()
now refers back to the argument through the
reference.
Graphical Representation:
8.5.5 Pass-by-reference
Passing by reference means the called functions'
parameter will be the same as the callers'
passed argument
(not the value, but the identity -
the variable itself).
A reference can be a convenient
shorthand for some object, is what makes them
useful as arguments.
Example:
// pass-by-reference (let the function refer back to the variable passed)
int f(int& x)
{
x = x+1;
return x;
}
int main()
{
int xx = 0;
cout << f(xx) << '\n'; // write: 1
cout << xx << '\n'; // write: 1; f() changed the value of xx
int yy = 7;
cout << f(yy) << '\n'; // write: 8
cout << yy << '\n'; // write: 8; f() changed the value of yy
}
Graphical Representation:
Application in Sorting (Swap function):
void swap(double& d1, double& d2)
{
double temp = d1; // copy d1’s value to temp
d1 = d2; // copy d2’s value to d1
d2 = temp; // copy d1’s old value to d2
}
int main()
{
double x = 1;
double y = 2;
cout << "x == " << x << " y== " << y << '\n'; // write: x==1 y==2
swap(x,y);
cout << "x == " << x << " y== " << y << '\n'; // write: x==2 y==1
}
8.5.6 Pass-by-value vs. pass-by-reference

Our rule of thumb is:
- Use pass-by-value to pass very small objects.
- Use pass-by-const-reference to pass large objects that you don’t need to modify.
- Return a result rather than modifying an object through a reference argument.
- Use pass-by-reference only when you have to.
8.5.7 Argument checking and conversion
When an argument is passed during a call, initialization of the function’s formal argument with the actual argument takes place.
void f(double x);
void g(int y)
{
f(y);
double x = y; // initialize x with y
}
There was a need to convert an
int
into a double
.
This happens in the call of f()
and also in f()
where double
value is stored in x
.
In conversions,
if a double
value has to be truncated
into an int
mention it explicitly.
void ggg(double x)
{
int x1 = x; // truncate x
int x2 = int(x);
int x3 = static_cast<int>(x); // very explicit conversion
ff(x1);
ff(x2);
ff(x3);
ff(x); // truncate x
ff(int(x));
ff(static_cast<int>(x)); // very explicit conversion
}
8.5.8 Function call implementation
Lets say we have functions expression(), term(),
primary()
.
A data structure is set aside which contains
copy of all parameters and local variables as soon
as a function is called.
A data structure called function activation
record which maintains information like the
function to which the caller needs to
return and return value is maintained.
Now, expression()
is called first:
expression()
calls term()
:
term()
calls primary()
:
And then primary()
calls
expression()
:
So this becomes a recursive function.
Each time when a function is called, the
stack of activation records (stack) grows
by one record.
When the function returns, the record is no
longer in use.
That means the stack reverts.
It works as "Last in, first out".
8.5.9 constexpr functions
A constexpr
function is a non-constructor
function declared with a constexpr specifier.
It is a function that can be invoked within a
constant expression.
Conditions to be satisfied by a
constexpr
function are:
- It cannot be virtual.
- Return type must be literal type.
- Also each of its parameters must be literal type as well.
- In a constant expression, each constructor call and implicit conversion is valid while initializing the return value.
- Function body is
= delete
or= default
- If not function body must contain null statements, static_assert declarations, typedef declarations, using declarations, using directives, one return statement
8.6 Order of evaluation

The evaluation/execution of a program proceeds
through statements according to the language rules.
The order of evaluation is as follows:
- Variable is constructed when the "thread of execution" reaches the definition of a variable
- Object is initialized by setting aside memory for the object
- Variable destroyed as it goes out of scope
- Object referred by the variable is removed
- Memory is free for the compiler to be used for something exclusively
string program_name = "silly";
vector<string> v; // v and program_name are global, they live until program terminates
void f()
{
string s; // s is local to f
while (cin>>s && s!="quit") {
string stripped; // stripped is local to the loop
string not_letters;
for (int i=0; i<s.size(); ++i) // i has statement scope
if (isalpha(s[i]))
stripped += s[i];
else
not_letters += s[i];
v.push_back(stripped);
// . . .
}
// . . .
}
8.6.1 Expression evaluation
If the value of a variable in an expression is changed, never read or write it twice in that same expression.
v[i] = ++i; // don’t: undefined order of evaluation
v[++i] = i; // don’t: undefined order of evaluation
int x = ++i + ++i; // don’t: undefined order of evaluation
cout << ++i << ' ' << i << '\n'; // don’t: undefined order of evaluation
f(++i,++i); // don’t: undefined order of evaluation
8.6.2 Global initialization
Global variables in a single translation unit are initialized in the order in which they appear.
int x1 = 1;
int y1 = x1+2; // y1 becomes 3
This initialization logically takes place
“before the code in main()
is executed.
const Date& default_date()
{
static const Date dd(1970,1,1); // initialize dd first time we get here
return dd;
}
The static
local variable is initialized
(constructed) only the first time its function is
called.
8.7 Namespaces
Classes are used to organized functions, data and types into a type. A function and a class both do two things:
- Allow to define a number of "entities" (without worrying about name clashes).
- Give a name to refer to what is defined.
A namespace is a language
mechanism for groupings of declarations.
It is used to organize classes, functions,
data and types into an identifiable and
named part of the program without defining a type.
namespace Graph_lib {
struct Color { /* . . . */ };
struct Shape { /* . . . */ };
struct Line : Shape { /* . . . */ };
struct Function : Shape { /* . . . */ };
struct Text : Shape { /* . . . */ };
// . . .
int gui_main() { /* . . . */ }
}
8.7.1 using declarations and using directives
Writing fully qualified names can be tedious.
#include<string> // get the string library
#include<iostream> // get the iostream library
int main()
{
std::string name;
std::cout << "Please enter your first name\n";
std::cin >> name;
std::cout << "Hello, " << name << '\n';
}
The above code can be reduced to:
#include<string> // get the string library
#include<iostream> // get the iostream library
using namespace std; // make names from std directly accessible
int main()
{
string name;
cout << "Please enter your first name\n";
cin >> name;
cout << "Hello, " << name << '\n';
}
It can be further reduced to by placing a
using
derivative for std
:
#include "std_lib_facilities.h"
int main()
{
string name;
cout << "Please enter your first name\n";
cin >> name;
cout << "Hello, " << name << '\n';
}
Test Yourself!

- What is the difference between a function declaration and a function definition?
- the declaration includes the function body, while the definition just gives the function's return and parameter types
- the declaration just gives the function's return and parameter types, while the definition includes the function body
- What are header files used for?
- To head off disaster.
- To put a nice header at the top of your code if you print it.
- To provide declarations needed for multiple source code files.
- How does indentation help in a C++ program?
- it helps the compiler do code optimizations
- it makes the structure of the code clearer to a human reader
- it is necessary to compile the code correctly, just as in Python
- If we need to alter the original of a variable we are passing to a function, we should...
- pass by constant reference
- pass by reference
- pass by value
- The function declaration consists of …
- function name, return type and parameter list
- function body and parameter list
- function name and parameter list
- Which of the following is not a type of scope?
- Namespace Scope
- Declaration Scope
- Class Scope
- Global Scope
- Passing by reference means …
- parameter will be the same as the callers' passed argument (not the value, but the identity - the variable itself)
- the called function's parameter will be a copy of the callers' passed argument
- Passing by value means …
- parameter will be the same as the callers' passed argument (not the value, but the identity - the variable itself)
- the called function's parameter will be a copy of the callers' passed argument
- Function definition consists of …
- function name and body
- function body and return type
- function name, parameters, return value type, and body
- What is the return type here: int myMethod(int count, double value) { return 4; }
- MyMethod
- int
- 4
- double
- count
- If a variable is declared inside a function, what kind of variable is this?
- global variable
- local variable
- class variable
- If we have a function int square (int n) , are we able to send it a different variable in the main program or does it have to be n. For example, square (x)
- No
- Yes
- Which of the following is a valid function call (assuming the function exists)?
- f();
- f;
- f x, y;
- int f();
- Identify the correct statement
- None of the mentioned
- A namespace is used to mark the beginning of the program
- A namespace is used to separate a class from objects
- A namespace is used to group classes, objects and functions
- What is the scope of the variable declared in a user defined function?
- none of the mentioned
- whole program
- the main function
- only inside the {} block in which it is declared
- If your function does not return any value, which of the following keywords should be used as a return type?
- double
- int
- void
- float
- unsigned short
- Which of the following functions should be defined as void?
- Return a sales commission, given the sales amount and the commission rate
- Print the calendar for a month, given the month and year
- Return a bool value indicating whether a number is even
- Return a square root for a number
- Which of the following should be declared as a void function?
- a function that prints integers from 1 to 100
- a function that checks whether current second is an integer from 1 to 100
- a function that converts an uppercase letter to lowercase
- a function that returns a random integer from 1 to 100
Answers
1. b; 2. c; 3. b; 4. b; 5. a; 6. b; 7. a; 8. b; 9. c; 10. b; 11. b; 12. b; 13. a; 14. d; 15. d; 16. c; 17. b; 18. a;
Drill
