C++

  • Created by Bjarne Stroustrup, starting in 1979 at Bell Labs
  • Direct descendant of C, which was introduced around 1973
  • Supports data abstraction and object oriented programming
  • Originally named C with Classes
  • Renamed C++ in 1983
  • Hugely successful and major influence on many other languages
  • Compiled language

 

This C++ essentials is starting from an assumed point that the user will already have a sound understanding of C, as a foundation to build upon.

 

Many of the fundamental concepts of C are encompassed within C++ and therefore only the main differences and advanced concepts are covered within this section of the site.

Programming

The art of writing language in a form that can be understood by a computer.

 

Computers work on a binary level, consisting of just two states; one and zero. Instructions are given to a computer in the form of machine code consisting of these binary digits.

 

The CPU is at the heart of a computer and utilises an ISA (Instruction Set Architecture) to provide programmers with a slightly more easier set of instructions to allow the computer to be told what to do. These instructions are in the form of Assembly Code, consisting of abbreviations that try to relate to human understandable words. e.g. mov eax, 123  means move the immediate value 123 into the eax register.

 

However, Assembly Code is (almost) just as difficult for humans to write first hand as machine code and therefore higher level languages are utilised to make it easier for us to write programs. The languages at this level are known as compiled languages, since they require the use of a compiler program to convert the human developed code (e.g. written in C++) into assembly, then machine code that can be understood by the CPU.

 

The compiler takes the source code written by the programmer in the high level language and converts it an executable file, which we then refer to as the program.

Compiling

Compiling is the act of taking a source code text file and running it through a compiler program to produce a program that can run on the computer.

 

 

Programmer writes the source code in plain text, often in an IDE (Integrated Development Environment)

 

The program is then compiled (converted) to a language that the computer can understand, and run as a program.

 

This is normally a two step process that consists of:

  1. Pulling in any specified header files and creating Assembly (or object) code native to the processor
  2. Using a linker program to pull in any other object or library files required, to finally output machine code (1's and 0's)

This resulting code is usually known as a binary or executable file.

 

The program can then be run (or executed) on the computer.

 

The GNU C++ compiler is invoked by opening a terminal and entering g++ on the command line.

 

Typically g++ takes at least two arguments; the file to be compiled and the output name:

 

g++ hello_world.cpp -o hello_world

 

*in windows, the output file type would need an .exe extension added to tell windows that its an executable program:

 

g++ hello_world.cpp -o hello_world.exe

Executable

Upon completion of the source code compilation the resulting (binary / machine code) file is now able to be executed upon the CPU type (/family) it was compiled upon.

 

Since different CPUs have different instruction sets, code compiled upon a machine with a CPU from say Intel, is incompatible with that of an ARM CPU.

 

However, it is generally possible to compile the source code upon a preferred target CPU platform to allow it to run (with perhaps a few tweaks to the code for the target platform). This conversion process is know as Porting.

 

The Operating System may require special configuration to allow an executable file to be run, such as using a .exe extension in Windows, or by using the execute bit on the permissions of a Unix/Linux system.

 

In general an executable file is more commonly known as a program.

Processes

The terms program and process are often used interchangeably. However, there are subtle differences:

 

  • Program = source code and/or compiled machine code. The instructions that tell the computer what to do.
    • Fixed storage size
  • Process = instance of a running program. The code loaded into memory, operating and working on data
    • Variable storage size (in working memory)
    • Includes the storage requirements of the loaded program plus its data

A unique pid (process ID) is assigned by the OS kernel to each process as an index for various data relating to the process

Standard Streams

Std Model

 

A computer system very simply acts upon input provided by either a human, another computer or built in procedures, which it then acts upon (computes) and provides the desired result as output.

 

stdin

Standard Input is usually received from the keyboard

 

stdout / stderr

Standard Out and Standard Error are usually sent to the screen

 

Term Location Abbreviation Signal
Standard In Keyboard stdin 0
Standard Out Screen stdout 1
Standard Error Screen stderr 2

 

Memory Layout

The Byte is the standard unit of storage, made up of 8 bits (binary digits) whose state can be 1 or 0.

 

Bytes have been shown on the LHS of the diagram below to indicate that the memory area comprises of a huge number of these (many millions/billions, etc, according to the amount of storage available). The BIOS and the OS, just as any other program, require storage and have been shown here for completeness.

 

The main areas we are interested in is the data segment (collectively consisting of the code, data and bss), the stack and the heap.

 

*note: bss is used by many compilers and linkers for the portion of an object file or executable containing statically-allocated variables that are not explicitly initialized to any value. It is often referred to as the "bss section" or "bss segment".

 

The following diagram provides a simplified view of how the memory is laid out:

 

 

 

 

OS, environment variables, command line arguments

 

 

 

 

Stack

 

Works on a LIFO basis

 

Used for local variables and passing arguments to functions,

along with return address of the next instruction to be

executed when the function call is over

 

When a new stack frame needs to be added (as a result of

a new function), the stack grows downward

 

 

 

 

Unallocated. Free area, available to be utilised for growth by

heap or stack

 

 

 

Heap

(aka Free Store)

 

Used for Dynamic Memory allocation

 

C      managed by malloc(), realloc(), free()

C++ managed by new, delete

 

 

 

 

 

 

 

 

 

BSS. Uninitialised data

 

Data segment. Initialised data. Global and static variables

 

 

 

Code segment. aka Text segment.

Contains the compiled Machine code (program) instructions.

Often r/o to stop it being overwritten.

 

 

Operating System

 

BIOS

 

 

*Note: this is greatly over simplified and shows just one program loaded in memory

Program Memory

When a program is compiled into an executable file, the compiler converts the program's executable statements (e.g. printf("Hello, World!"); ) that are of a specific size into machine code, and also knows how much room to allocate for the global and static variables (from their data types), thus resulting in a fixed amount of storage for the compiled program.

 

When a program is executed (aka running) it is often referred to as a process (e.g. on a Linux system), and is allocated four areas of memory:

  • Stack
    • Return address
    • Function parameters (passed in arguments)
    • Local variables
  • Heap
    • aka Free Store
    • Dynamic memory allocation
  • Data
    • Initialised global and static variables
    • Uninitialised variables
  • Code
    • Executable statements in machine code

 

Upon program execution the OS provides a new VAS (Virtual Address Space) for each process, whereby each virtual address is mapped to physical memory by use of a structure known as a page table. This is an abstraction of physical memory and the process effectively considers the full amount of memory available to it (as logical addresses). On a 32bit OS, the process has a 4GB VAS (2^32).

 

In reality, many programs are running at the same time with the underlying OS taking care of memory management.

 

The following represents two processes virtual address spaces being mapped to physical memory:

 

 

This representation shows the a single program being run as two processes (e.g. two instances of a text editor), sharing the same code segment in physical memory but with their own data and stack segments:

Stack

The stack is comprised of a number of Stack Frames, with each frame representing a function call.

 

The size of the stack increases in proportion to the number of functions called, and then shrinks upon return of a completed function.

 

Works on a LIFO basis.

 

Each stack frame contains:

  1. The returning line number
  2. Any arguments from the called function
  3. Storage space for all of the function's (automatic) variables
  4. (various bookkeeping data)

Consider the following program, containing two functions:

 

  1. Upon program start an initial stack frame is created for main()
  2.  
     

  3. firstFunc() is called and a new stack frame is created from unused stack memory, containing:
    1. Line to return to = the line after where it was called from in main() = Line 9
    2. Storage space for an int
  4.  

  5. secondFunc() is called and a new stack frame is created from unused stack memory, containing:
    1. Line to return to = the line after where it was called from in firstFunc() = Line 15
    2. Storage space for an int
    3. Storage space for a char
  6.  
     

  7. When secondFunc() returns, it's frame is used to determine where to return to (line 15 of firstFunc()), then deallocated and the space returned to the stack
  8.  
     
     

  9. When firstFunc() returns, it's frame is used to determine where to return to (line 9 of main()), then deallocated and the space returned to the stack

When main() returns, the program ends.

 
 

Hello, World!

This is one of the most important programs a programmer will write, since it not only shows that the programmer has managed to create the code correctly, but has also implemented a working environment to develop and run the code.

 

Compile & Run:

Hello, World!

Storage Class & Scope

The storage class of a variable refers to its lifetime during program execution.

 

The scope of a variable refers to its visibility.

 

The location at which a variable is declared, determines where it will be placed within memory.

 

Variables declared outside of any function have global scope and static (permanent) duration.

 

Variables declared within a function have local scope and automatic (temporary) duration.

 

Data Types

The concept of Data Types is Extremely Important and often given just a cursory glance, especially by newbies.

 

However, data types are at the core of how the compiler works out how to determine a program's storage requirements.

 

The more complex data types (covered later) similarly define storage requirements for the object being specified.

 

At this point it is important to know that all objects must have a data type, which ultimately define their storage requirement.

 

Also, expressions and functions are preceded with a data type, to inform the compiler...

 

Fundamental Data Types:

char 

short

int

long

float

double

bool

void

Single character 

Short integer

Integer whole number

Long integer

Floating point number correct to 6 decimal places

Floating point number correct to 10 decimal places

Boolean value of TRUE (1) or FALSE (0)

No value returned

D 

65535

4294967295

4294967295

17.031963

12.0270140242

True or 1, False or 0

-

1 Byte 

2 Bytes

4 Bytes

4 Bytes

4 Bytes

8 Bytes

1 Byte

-

0-255 

0-65535

4294967295

4294967295

+/-3.4e+/-38

+/-1.7e+/-308

true or false

-

 

The progression of the data types evolves from the primitives above, to:

 

  • compund data types
    • arrays
    • multi-dimensional
    • strings
    • vectors
    • structures
    • unions
  • abstract data types
    • class -> objects

 

I hope to show the transition from the basic to the complex, in the hope that others will have a similar 'eureka' moment as I had.

 

I think the whole ethos behind this, is learning the concepts in the correct sequence - build upon foundations...  which means getting the concepts ordered properly, and explaining them properly. no bs = cut the crap.

typedef

The typedef keyword is used to allow user defined data types based on existing data types to be defined.

 

Thus enabling a user created alias for an existing data type to be defined.

 

The syntax is:

 

typedef existing_type new_type ;

 

e.g.

 

typedef long int spokes ;

 

The above shows that a new datatype called spokes has been defined as being equivalent to a long int, and the two could thereon be used interchangeably within the program it was defined in.

 

spokes myVar ;    is equivalent to    long int myVar ;

enum

Allows the creation of user defined (enumerated) data types.

 

Enumerated data types consist of a value defined as a symbolic constant, known as an enumerator, starting from zero.

 

Compile & Run:

The enum in the 5th element is Green with a value of: 5

 

 

The defined variable (myValue from above) could have been declared along with the enum definition, as per line 16:

Compile & Run:

The enum in the 5th element is Green with a value of: 5

 

 

Specific values can also be defined:

Compile & Run:

The enum in the 5th element is Green with a value of: 42

cout

Displays output to stdout, usually the (console's) screen.

 

C++ uses the cout object defined with the standard namespace of the <iostream> header file.

 

cout is the name given to the standard output stream stdout.

 

Used with the << operator to send the specified string to stdout.

 

Generally closed off with an end of line symbol denoted by endl, and closed with a semi-colon ;

 

A major difference to C's printf() function.

 

Compile & Run:

This is just a test string of characters!

cin

Acquires input from stdin, usually the (console's) keyboard.

 

C++ uses the cin object defined with the standard namespace of the <iostream> header file.

 

cin is the name given to the standard input stream stdin.

 

Used with the >> stream extraction operator to send the incoming entered stream from stdin to a specified variable.

 

Closed with a semi-colon ;

 

A major difference to C’s scanf() function.

 

Compile & Run:

Please enter your first name:Gomez 

You entered: Gomez

 

 

Or getting more than one value, as per line 10:

Compile & Run:

Please enter your first name, and your age:
Harriette
33
You entered your name as: Harriette and your age as: 33

 

 

*Note: that cin stops reading the input stream as soon as it reaches the first blank space character.

 

To acquire a whole sentence, including blanks, the getline() function is preferred:

Compile & Run:

Please enter the name of your favourite band:
The Fall
Yeah, The Fall Rock!

Comments

Use // for a single line

 

Use /* for

Multiple lines
*/

 

main()

The place at where execution of a program starts.

 

The parentheses ( aka brackets ) following the identifier, which are then then followed by curly braces { with an enclosed code block }, indicate that this is a function.

 

ALL programs have at least one function; main()

Compile & Run:

Hello, World!

Statement

A statement is an instruction that tells the computer to do something.

 

Always terminated with a semi-colon ;    (*except preprocessor directives #define, #include)

 

e.g.

cout << "Hello, World!" << endl ;  //instruction to print the string, nothing has been evaluated

int a ;  //instruction to allocate storage for (declare) an integer, nothing has been evaluated

 

The above examples show statements to instruct the computer to do something.

 

If a statement needs to go over to the next line, a backslash should be used:

The backslash indicates another line is being used, and we can still see that the overall statement is terminated by the semi-colon ;

 

Compile & Run:

Hello, World!

Expression

An Expression is a line of code that evaluates to a value.

 

e.g.    a = b* c

 

All expressions have a type and a result.

 

An expression (e.g. a = b * c ) becomes a statement when followed by a semi-colon (i.e. a = b * c ; )

 

So, basically, an expression is the computational section of the code.

 

C++ definition: "a sequence of operators and operands that specifies a computation".

 

 

The 3 comma separated expressions on line 9 could have been separated on to individual lines, creating 3 statements.

Compound Statement / Code Block

A group of statements enclosed within curly braces { }

 

Commonly referred to as blocks.

 

Can be nested to bring common items together and to restrict scope.

Identifiers

Identifiers are names given to identify a specific entity (e.g. a variable, function, constant, object, etc), allowing them to be referred to.

 

Just like algebraic substitutions in maths.

 

The names can consist of the 26 letters of the Latin alphabet (upper/lower case), the 10 Arabic/Western numerals and the ASCII underscore character _

 

 

CANNOT:

Start with a number

Be any of the C++ language reserved / key words

 

 

ALL identifiers, statements, expressions, etc, are cAse SensITiVe !!!

Keywords

C++ has 63 keywords for its own internal use, which CANNOT be used for any other purpose:

 

asm insert an assembly instruction
auto declare a local variable
bool declare a boolean variable
break break out of a loop
case part of switch statment
catch handles thrown exceptions
char declare a character variable
class declare a class
const declare immutable data
const_cast cast from const variables
continue bypass iterations of a loop
default default handler in a case statement
delete free memory
do loop
double declare a double precision floating point variable
dynamic_cast perform runtime casts
else alternate case for an if statement
enum create enumerated types
explicit only use constructors when they exactly match
export
extern tell the compiler about variables defined elsewhere
FALSE Boolen value false
float declare a floating point variable
for loop
friend grant non-member function access to private data
goto jump to a different part of the program
if execute code based on the result of a test
inline expand a call to a function rather than calling that function
int declare an integer variable
long delcare a long integer variable
mutable override a const variable
namespace partition the global namespace by defining a scope
new allocate dynamic memory for a new variable
operator create overloaded operator functions
private declare private members of a class
protected declare protected members of a class
public declare public members of a classa
register request that variable be optimised for speed
reinterpret_cast change the type of a variable
return return from a function
short declare a short integer variable
signed modify variable type declarations
sizeof return the size (in Bytes) of a variable or type
static create permanent storage for a variable
static_cast perform a nonpolymorphic cast
struct create a new structure
switch execute code based on the different possible values for a variable
template create generic functions
this a pointer to the current object
throw throws an exception
TRUE Boolean value true
try execute code that can throw an exception
typedef create a new type name from an existing type
typeid describes an object
typename declares a class or undefined type
union a structure that assigns multiple variables to the same memory location
unsigned declare an unsigned integer variable
using used to import a namespace
virtual create a function that can be overridden by a derived class
void declare functions or data with no associated data type
volatile warn the compiler about variables that can be modified unexpectedly
wchar_t declare a wide character variable
while loop

source

Variables

A variable is simply an identifying name for a memory address.

 

A bit like a telephone book, where names are matched to numbers. After-all, it's much easier for us humans to work with names than having to deal with large and complex hexadecimal numbers.

 

 

The data type of a variable simply tells the compiler how much memory space to allocate.

 

So, given that an int takes four bytes, and if it were assigned a memory address of 0x00002010, the next available memory address would be 0x00002014.

 

Similarly, an array is assigned [N] memory allocations for its datatype, and so on for structs, unions, classes, etc.

 

So a variable is simply a name for the starting memory location for the object being declared.

 

Variables (or any other type of object) can be thought of as containers of specified information. If instructed, this information can be changed and the contents of that container will reflect the instructed change.

 

Being an Object Oriented language, the term object is generally interchangeably used in C++ when referring to variables, structs, unions, objects that use identifiers to give them unique names.

Declarations

The act of declaring an object (including variables, statics, etc.) instructs the compiler how much storage to allocate.

 

All objects must be declared before they can be used.*

 

A declaration specifies a data type and a list of one, or more identifiers (names) to call the variables / objects

 

int myVar ;

 

or:

int myVar, cat, dog, potato ; //4 integer variables declared

 

Multiple identifiers are separated by a comma. The above declares four variables of the data type int called myVar, cat, dog, potato.

 

*Note: Later we will see that functions must also be declared before they can be used

Definitions

Definitions – aka initialisation

 

Variables are defined/initialised by use of the assignment operator =

 

int myVar ; //declaration only

 

myVar = 123 ; //definition only

 

int myVar = 500 ; //declaration and definition

Assignment

A SINGLE equals character =  is used to assign a value to a memory address. This memory address is usually in the form of an identifier name.

 

int myVar ;  // declare an integer called myVar

 

myVar now has an allocated address space and storage space, BUT it has NOT been assigned a value.

 

A value can now be assigned using a single equals character:

 

myVar = 42 ;  //the value 42 has now been assigned to myVar

Constants

Constants are expressions with a fixed value.

 

  • Literals
    • Specific values assigned to an identifier
    • Numerical
      • Integer
        • myVar = 17 ;
      • Floats
        • yourVar = 32.548 ;
    • Characters
      • Single character between 'single quotes'
      • Important to use quotes, otherwise it could refer to another variable called D
      • myChar = 'D' ;
    • Strings
      • String of characters between "double quotes"
      • myString = "Selenium" ;
    • Booleans
      • TRUE or FLASE
  • Defined
    • Used by the preprocessor
    • Syntax: #define IDENTIFIER value
    • Note, no semi-colon ;
    • Common practice is to define the identifier in UPPERCASE
    • #define PI 3.14159

 

  • Declared
    • Utilises the const keyword
    • Cannot be changed after they've been defined
    • Common practice is to define the identifier in UPPERCASE

Type Casting

Explicitly converts data types.

 

Syntax:  (target_data_type)identifier ;

 

Compile & run:

42 / 17 WITHOUT type casting: 2
42 / 17 WITH type casting: 2.47059

Operators

Arithmetic
+
-
*
/
%
++
– –
Addition
Subtraction
Multiplication
Division
Modulus
Increment
Decrement
a
a
a
a
a
a
a
+
-
*
/
%
++
– –
b
b
b
b
b
b
b
Assignment
=
+=
-=
*=
/=
%=
Assign to
Add and assign
Subtract and assign
Multiply and assign
Divide and assign
Modulus and assign
a
a
a
a
a
a
=
+=
-=
*=
/=
%=
b
b
b
b
b
b
Comparison
==
!=
>
<
>=
<=
Equality
Inequality
Greater than
Less than
Greater than or equal
Less than or equal
a
a
a
a
a
a
==
!=
>
<
>=
<=
b
b
b
b
b
b
Logical
&&
||
!
And
OR
NOT
a
a
a
&&
||
!
b
b
b
Conditional
a > ? : Ternary a > b ? c : d

 

 

& address of operator

* derefencing operator

. member operator

-> infix operator, aka pointer member dereferencing operator

<< insertion operator

>> extraction operator

Precedence

Simplified!

  1. * / before + -
  2. ( ) around everything else

If in doubt ( use these )

Prefix / Postfix

Refers to the use of the shorthand ++ incrementer or -- decrementer, either before (Prefix) or after (Postfix) the variable it is being applied to.

 

Prefix:  ++myVar    //increment, then use

 

Postfix:  myVar++    //use, then increment

 

Prefix will increment the variable before it is used

 

Postfix will use the variable before it is incremented, then increment the variable

 

If used on their own, the result is identical. It is only when combined with other expressions that differences appear:

Compile & run:

myVar starts off as: 5
Prefixing myVar makes a: 6
myVar is now: 6
Postfixing myVar makes b: 6
myVar is now: 7

if, else if, else

Tests if a condition is TRUE or FALSE.

 

If the test condition equates to boolean TRUE, the code block following the condition parentheses is executed.

 

Syntax:

if(test condition) {

//do this code if TRUE

}

//otherwise condition is FALSE, so continue

 

Optional else if conditions can follow, as well as optional else statements:

 

Compile & Run:

Please enter your favourite number:
66
66 is less than 100!

Ternary ? :

Similar to the if statement, tests if a condition is true or false.

 

aka 'conditional operator' or the 'arithmetic if' operator.

 

Syntax:

condition ? true : false ;

 

Line 14, assigns the result of the ternary test condition to the uninitialised variable max:


Compile & Run:

Please enter the 1st number:
5637
Please enter the 2nd number:
12
The larger number was: 5637

 

switch, case

Tests a condition against any number of case conditions.

 

Break must be used to terminate the switch, or the next statement will be executed.

 

A default case is utilised for when no condition is met.

 

while

Loops through the statements enclosed within the { code block } until the test_expression is false:

 

while (test_expression) {
statements ;
}

 

Compile & Run:

myVar is now: 0
myVar is now: 1
myVar is now: 2
myVar is now: 3
myVar is now: 4

 

*Note: interestingly, the compiler set the uninitialised myVar to 0.

However, this is bad programming practice and in reality should be defined.

 

Also note, it is possible to simply treat myVar as a boolean in the while test parentheses:

Compile & Run:

myVar is now: 5
myVar is now: 4
myVar is now: 3
myVar is now: 2
myVar is now: 1

 

 

Line 8  could have been written as while (myVar > 0) { but since it decrements to 0, and 0 is the same thing as FALSE, it is possible to simply treat myVar as a boolean in this case.

do

Loops through the statements enclosed within the { code block } until the following while test expression is false:

 

do {
statements ;
} while (test expression) ;

 

*note the ending semi-colon ; after the while test expression!

 

Compile & Run:

myVar is now: 0
myVar is now: 1
myVar is now: 2
myVar is now: 3
myVar is now: 4

for

Iterates through the loop, starting from the specified initial condition and will iterate through the statements enclosed within the { code block } until the test is false. The initial condition, test and iterator are separated with a semi-colon ;

 

Syntax:

for (initialisertestiterator ) {

statements ;

}

 

Compile & Run:

myVar is now: 0
myVar is now: 1
myVar is now: 2
myVar is now: 3
myVar is now: 4

break

Terminates execution of the nearest enclosing do, for, switch, or while statement in which it appears.

 

Compile & Run:

myVar is now: 0
myVar is now: 1
myVar is now: 2
myVar is now: 3

continue

Passes control to the next iteration of the nearest enclosing do, for, or while statement in which it appears, bypassing any remaining statements within that code block.

 

Compile & Run:

myVar is now: 0
myVar is now: 1
myVar is now: 2
myVar is now: 4
myVar is now: 5
myVar is now: 6

Scope

The concept of Scope refers to where an object is valid, i.e. where it can be uniquely used. Sometimes referred to as its spatial region.

 

(*Note: The term Object is being used interchangeably for variables, etc)

 

An object is not valid until it has been declared.

 

An object becomes valid from the point at where it is declared.

 

An object with:

  • Local Scope
    • aka Block Scope
    • Has validity from the point within the block in which it was declared
    • i.e. within the {code block, between the curly braces }
    • Nested Block Scope
      • Inner object overrides outer object
      • i.e. if outer object has same name as inner object, only the inner object will be valid within that nested block
  • Function Scope
    • Object is valid from the start to the end of the function
    • Object should be uniquely identifiable
  • Global Scope
    • aka Program Scope
    • Objects declared outside of a function (including main)
    • Valid from the point at which it was declared
    • File scope
      • Another type of global scope
      • Objects are valid within the scope of the source file in which it was declared
      • Slightly different to program scope, whereby the object is valid within all other (included / linked in) files
      • e.g. variables declared static

 

Assuming no other same named object exists within the lower layers, an object with:

  • Program scope is valid within all layers
  • File scope is valid within the File, Function and Block layers
  • Function scope is valid within the Function and Block layers
  • Block scope is only valid within its own block

Illustration of visibility of scope, whereby outer layers can be seen by inner layers, but inner layers can not be seen by outer layers.

 

 

 

Program to illustrate scope, using a singly defined variable, theVar:

Compile & Run:

The value of theVar from the global scope is:17
The value of theVar in this outer block is: 3
The value of theVar in this inner block is: 36
The value of theVar within this nested inner block is: 42
Taking the outer block value of theVar (3) and adding its square (9) = 12

 

Notice that there is only one named variable called theVar. However we can uniquely act upon its multiple specific vales, depending on how and where it is declared and used.

Storage Specifiers

Storage class relates to when and where an object is valid.

 

The scope of an object identifies where an object is valid, i.e. its spatial properties

The storage class specifiers (and modifiers) identify when an object is valid, i.e. its temporal properties

 

by keyword:

  • auto
    • Inidcates that the memory location is temporary
    • Only applies to local (block) scoped objects
    • Default for locally (block) scoped objects, and therefore rarely used in practice
  • static
    • Indicates that the memory location is permanent
    • Applies to Globally or Locally scoped objects
    • Object's last value remains in memory, even if the object goes out of scope
  • register
    • Literally a hardware register in the CPU
    • Has no memory location address
    • Used where fast speeds are required
    • Compiler only takes the keyword as a suggestion, not guaranteed
      • Might not use if a register is unavailable
  • extern
    • Refers to an object in an external file
    • external file needs to included at time of compilation
      • e.g. gcc myProg.c extProg.c -o outputFile

 

A couple of small programs to illustrate Storage Class Specifiers:

Compile & Run (g++ myProg.cpp  extProg.cpp  -o outputFile):

Just proving we can call in an external object: 6
Function call 1: Multiplying 0 by 6 = 0
Function call 2: Multiplying 1 by 5 = 5
Function call 3: Multiplying 2 by 4 = 8
Function call 4: Multiplying 3 by 3 = 9
Function call 5: Multiplying 4 by 2 = 8

Storage Qualifiers

aka Storage Modifiers

 

by keyword:

  • const
    • Cannot be changed after its been initialised
    • e.g. const double PI = 3.141592654 ;  //assigns the defined value to an identifier named PI
  • volatile
    • Value in memory can be changed despite no direct modification by any of the program code
    • e.g. a pointer to a hardware location that contains the time, where hardware changes the value of this pointer variable and not the program
    • volatile int current_time ;  //declares a volatile variable
  • mutable
    • Member of a structure or class can be altered even if a particular structure variable, class, or class member function is constant
    • i.e. a mutable member can be modified by a const member function 

 

References

An alias for a variable

 

Utilises the ampersand & symbol

 

Syntax:    int & myAlias = myVar ;  //now myAlias and myVar are effectively the same

 

Any changes to the reference are reflected in the original, and vice-versa.

 

References are similar to pointers, but do not work under the principles of 'address of' or dereferencing.

 

  • alias for a variable
  • when declaring must be initialised to a variable
  • cannot have NULL references
  • data type (primitive or abstract) must precede the ampersand &
    • dataType & alias

This example assigns two references and also shows references being passed into a function:

Compile & Run:

a before swap: 17
b before swap: 42
a after swap: 42
b after swap: 17

 


*Note: Maybe slightly confusing with respect to the ampersand & symbol also being used as the 'address of' operator. The thing to remember with references is that they should always be initialised to an existing variable.

Functions

All programs must at least have the main() function.

 

Functions are used to modularise a program, breaking it down into smaller chunks that can be called upon when necessary.

 

Syntax:

return_datatype function_name (parameter, list) {

code block statements ;

}

 

return_datatype is the expected return datatype as required by the caller invoking the function. If the function doesn't need to return anything, the void return data type should be used.

 

function_name is the programmer defined identifier for the function.

 

The parameter list is contained within the parentheses following the function name, and is made up of zero of more comma separated parameters (aka arguments, aka formal parameters). The data type, order and number of parameters must match what is being sent to the function by the caller. The parameter names can be different from those of the caller, as long as the function uses the same identifier names within its { code block }.

 

For instance, say a function is being called within main() using a and b as its sending parameters: myFunc(a, b) ;  The function can then use its own parameter names within the function, e.g.

 

int myFunc(int x, int y) {

return(+ y) ;

}

int main() {

int a = 2, b = 3 ;

myFunc(a, b) ;

return 0 ;

}

 

Notice that the caller used the variables a and b, but the function accepted them to be used within its code block as x and y. The main thing that we should be worried about is that the return value is of the correct data type.

 

The function name and parameter list are known as the function signature. Also sometimes referred to as the extended name.

 

The function body contains a collection of statements defining what the function does. This can be as simple as sending a string to the console, or computing and returning a value.

 

The term for using a function is to 'call' a function.

 

A function is called by using the function name along with any parameters required.

 

Compile & Run:

Hello, World!

17 + 42 = 59

 

 


Initialised parameters

It is also possible to initialise the value of the parameters, so that in the event of no parameter value being passed in, the function will use its initialised value as a default for use within the function:

e.g.:

int add(int x, int y = 23) ; {

return x + y ;

}

Prototypes

A function prototype, consists of a return data type and function signature, but has no code block and is terminated by a semi-colon ;

 

Syntax:

return_datatype function_name (parameter, list) ;

 

This informs the compiler of what to expect in terms of memory resources for the function, by letting main() know what data type it returns along with the argument data types the function expects.

 

The format of the prototype must match the actual fully coded function (in terms of the return data type and function signature), or there will be compiler errors.

 

Prototypes allow a program to be developed without having to completely work out all the code for each function in advance. This approach allows the logical flow of the main() section of the program to be developed, and then concentrate upon the functions code body.

 

Remembering, all functions and variables must be declared before they can be used.

 

The full code of the function is then defined after main()

Compile & Run:

Before swap: 17, 42
After swap: 42, 17

 

 

This methodology is called function prototyping, and provides a neat way to structure your programs with as many functions as required following main().

 

This also gives the code good readability, as one can easily dip in and out of main() when reading the code, to view the required function, understand what its doing and what its returning (if anything) back into main().

return

Terminates execution of a function and returns control to the point immediately following the function call, where upon execution continues.

 

In the case of the main function, control is transferred back to the operating system.

 

Syntax:

return [expression] ;

 

The value of the expression is returned to the calling function.

 

If there is no expression the return value is said to be undefined.

 

Void functions do not and cannot have a return expression. You may also sometimes see a void function with no return statement, thus being undefined.

 

All other types of function must specify a return expression.

 

Compile & Run:

42 is larger than 17

 

 

You will often see return 0 ;  just before the end of main(). This is known as the application exit status, which is returning a value of 0 to the operating system. Standard convention has main() being declared with int preceding it, hence the ability to return a number to the OS, which can potentially be used by other programs or the OS as necessary. For instance, if an application exited with a return value of 1, this might alert the OS or other application that something went wrong, and can be acted upon accordingly.

Pass by Value

When a parameter is passed into a function by value, the compiler takes a copy of that passed in value for ongoing use within the function and any execution upon that value is local to that function only, i.e. it does not effect the passed in value by the caller outside of the function.

 

Upon completion of the function, any changes to the copied in value are lost.

 

The passed in values do not have to use the same identifier name as those outside of the function. e.g. a and b in main() can be called x and y within the function. What matters is the order in which they're used and their type:

Compile & Run:

x and y in myFunc: 289, 1764
a and b in main: 17, 42

Pass by Reference

Passing a value by reference allows the actual value outside of the function to be acted upon, as opposed to a copy of the value.

 

In passing a value by reference, C++ differs from C in that it allows any type of reference to be used (as opposed to just a pointer reference in C).

 

Accordingly, C++ allows values to be passed in using their normal identifier, and are then accepted within the formal parameter list of the function using the ampersand & (address of) reference operator:

 

Compile & Run:

a and b in main before swap: 17, 42
x and y in myFunc: 42, 17
a and b in main: 42, 17

 

Notice the swap of the values within the function has also affected the values in main()

Pass by Pointer

Similar to the pass by reference method of passing actual values to a function, this method uses pointers (akin to the C method) to act upon the actual data being passed in.

 

In this case, the address of the variable is sent by the caller to the function, which accepts the incoming parameters as pointers. The pointers are then used within the function:

 

Compile & Run:

a and b in main before swap: 17, 42
x and y in myFunc: 42, 17
a and b in main: 42, 17

Function Overloading

Function Overloading allows a same named function to be used, that will act differently depending upon how it is invoked. Specifically, it depends upon the data type, number and order of arguments in the parameter list.

 

For instance, say you wanted to add two numbers but had different data types; integers and floats. If a single function was used accepting integers as its formal parameters, any precision required for floating point numbers would be lost.

 

Therefore, another similar function can be created that accepts floats, to keep the precision:

Compile & Run:

17 + 42 = 59
1.234 + 5.678 = 6.912

Pointers

The concept of pointers simply defines another identifier, declared as a pointer, for an existing object.

 

Pointers consist of a memory address that has been assigned the memory address of the object they are being pointed to.

 

Pointers are declared using an asterisk * between the data type and the identifier. The positioning of the asterisk is down to personal preference of programming style:

 

int * myVar ;

int* myVar ;

int *myVar ;

 

 

Although the actual contents of a pointer consist of a memory address, the data type of a pointer must match the data type of the object it is pointing to. This ensures the compiler allocates the correct amount of memory space for the object being pointed to:

 

int *myInt ; //declares a pointer that will point to an int

char *myChar ; //declares a pointer that will point to a char

float *myFlt ; //declares a pointer that will point to a float

 

The ampersand & 'address of' operator is used to assign the address of an existing object to the pointer object:

 

int myVar ;  //declaration

myVar = 5 ;  //definition

int *myPtr ;  //declaration

myPtr = &myVar ;  //definition

 

As with other variables, a pointer can be initialised at time of declaration:

 

int myVar = 5 ;  //integer declaration & definition

int *myPtr = &myVar ;  //pointer declaration & definition

 

*myPtr is now equivalent to myVar, and the two can be used interchangeably for the same object.

 

The use of the asterisk * indicates that it is the value of the object being pointed to that is being referred to, this concept is know as dereferencing the pointer.

 

Compile & Run:

a: 17, *aPtr: 17
b: 42, *bPtr: 42

 


 

If one were to display the contents of the pointer (without the asterisk), you would only see the address of the object being pointed to.

Void Pointer

Void pointers do not have any data type of their own and can therefore be assigned to point to ANY other data type.

 

Represents just the address of an object but not its data type.

 

CANNOT be dereferenced directly - HAS to be typecast to the data type of the object being pointed to

 

Compile & Run:

value: 12
value: 14.6345
value: 14.6345

 

 

*Note: Unlike C, you cannot implicitly cast from void * in C++. In C++ it must be explicitly cast

 

source

NULL Pointer

Special value that indicates that it is not pointing to any valid reference or memory address.

 

Can be assigned using NULL, 0 or nullptr:

Compile & Run:

Assigned using NULL: 0
Assigned using 0: 0
Assigned using nullptr: 0

Pointer Arithmetic

Since pointers are declared of a specific data type they are allocated a specific amount of memory according to that data type.

 

Arithmetic is carried out based upon the units of allocated memory, by data type.

 

For instance, a char pointer is allocated one byte, an int pointer is allocated four bytes, arithmetic carried out upon these would be by the size of the data type; accordingly, a single increment of an int pointer would increase the pointed to address by four bytes, that is, the next integer.

 

Similarly, incrementing a char by one would increase the pointed to address by one byte:

Compile & Run:

charArr[0] contains: V at address location: 0x28fef1
charArr[1] contains: a at address location: 0x28fef2
charArr[2] contains: n at address location: 0x28fef3
charArr[3] contains: e at address location: 0x28fef4
charArr[4] contains: s at address location: 0x28fef5
charArr[5] contains: s at address location: 0x28fef6
charArr[6] contains: a at address location: 0x28fef7

 

 

*Note: the address is having to be type cast (on line  12) due to cout overloading the << operator

source

Arrays

aka Array Data Structure.

 

Sequential collection of same data type variables.

 

Declared by use of [square brackets]:

 

Syntax:    data type array Name[array size] ;

 

Values in the array are referred to as elements, and ALWAYS START FROM ZERO!

 

int myArray[10] ;  //declares an array called myArray that can contains 10 elements of the int data type

 

Defined by assigning comma separated values, within { curly braces }

 

int myArray[10] = {2, 3, 7, 12, 14, 17, 42, 63, 70, 99} ;

The number of elements defined must exact match the number of elements declared.

 

Alternatively, an array can be defined without having to specify the number of elements, in which case the compiler will automatically size the array upon definition of the elements:

 

int myArray[] = {3, 13, 1, 56, 33} ; // array will be automatically sized to hold the number of elements defined

 

 

Array index

Integer pointer for each element of the array. An array sized with 10 elements (e.g. int arr[10] ;) has 10 index pointers for each element starting from 0, progressing to 9.

 

Single array elements can be defined by assigning a value to the required index number of the element (starting from zero) using the square brackets [ ], aka subscript:

 

myArray[6] = 21 ; //assigns the value 21 to the 7th element

 

Similarly, elements can be accessed by specifying the required index number of the element (starting from zero):

 

int myVar = myArray[4] ; //access the 5th element of myArray and assigns it to myVar

 

Compile & Run:

Uninitialised values:
2686916
1985711317
-1992624055
-2
1985614178 

Initialised values:
9
6
8
2
5

Array values initialised at declaration:
5
9
2
5
8

Pointers & Arrays

An array is a variable that contains N values of the same data type.

 

A variable contains just one value of a specified data type. Declaring a variable is the act of giving a name to the address where the value of the specified data type will be stored.

 

i.e. int myVar ; //declares an integer called myVar. This allocates address space for an int, which we can refer to by its name, myVar

 

The address of myVar can be seen using the ampersand address of operator &myVar, which display a hex address 0x123456

 

Arrays are sized either upon declaration or definition: int myArr[5] ; or int myArr[] = {9,8,7,6,5} ; in the latter case, the compiler automatically sizes the array for the defined values.

 

The compiler allocates contiguous storage for the named array according to the specified data type, multiplied by the number of elements. e.g. an int array with 5 elements would be allocated 4 (number of bytes for an int) x 5 (elements) = 20 bytes = 20 (8bit) address spaces.

 

So, declaring an array gives a name to the first allocated address. If we were to display the array name on its own, we would see the address of the first element in the array.

 

e.g. cout << myArr ; //would display the address of the first element of the array called myArr, as would cout << &myArr ; and cout << &myArr[0] ;

 

Thus myArr, &myArr and &myArr[0] are equivalent, and contain the address of the first element of the array!

 

Since the compiler knows the data type units (i.e. the amount of storage required for the specified data type), arithmetic is carried out upon the name of the array in units of the decalred data type. e.g. an int array has four bytes per element, thus adding 2 to the array identifier name tells the compiler to add 2 address units (as per the data type) which would allow access to the third element of the array

 

e.g. following on from the array defined above, myArr+2 is the address of the third element

 

Since we now know that the name of the array contains the address of the first element of the array, we can declare a pointer of the same data type and assign it with that array address:

 

int *myPtr = myArr ; //which is the same as *myPtr = &myArr

 

myPtr now contains the address of myArr, and can be dereferenced as per normal pointer operations:

 

cout << *myPtr ; //displays the value of the first element in the array

 

It now makes sense that we can perform simple arithmetic operations (e.g. increment/decrement) upon the pointer, to access the desired element within the array.

 

e.g. myPtr+2

 

However, it must be remembered that this is incrementing the address, which now equates to the 3rd address within the array.

 

To obtain the value within that address, it must be dereferenced, taking care of operator precedence!

 

Important! * comes before + in terms of operator precedence, and therefore to access the value in the third element of the array, the dereferencing must be applied to the incremented address (normally carried out within parentheses).

 

e.g. *(myPtr+2)

 

If we were to dereference directly against the addition expression, like so: *myPtr+2 this would firstly dereference myPtr (which has a value of 9) and then add 2 to it, giving an equated value of 11.

 

But since we actually want the third element in the array, we apply the addition expression within parentheses like so: (myPtr+2), and then dereference that, giving: *(myPtr+2) which has a value of 7.
e.g. cout << *(myPtr+2) ; //to access the value in the 3rd element

 

A for loop is commonly used to iterate through the values in an array

 

Compile & Run:

Contents of myArr:     0x28fee4
Contents of &myArr:    0x28fee4
Contents of &myArr[0]: 0x28fee4
The value of the third element using array subscript is: 7
The value of the third element using pointer arithmetic is: 7 

The value of the third element using pointer arithmetic is: 7
Element [0] at address 0x28fee4, contains 9
Element [1] at address 0x28fee8, contains 8
Element [2] at address 0x28feec, contains 7
Element [3] at address 0x28fef0, contains 6
Element [4] at address 0x28fef4, contains 5

 

 

*Note: On line 17, the array can also be dereferenced directly (using myArr), without the need for a separate pointer as per line 16 (using myPtr) - note the subtle difference!

 

Another simple example:

Compile & Run:

myArray element0 contains: 42
myArray element1 contains: 0
myArray element2 contains: 6
myArray element3 contains: 0
myArray element4 contains: 7
myArray element5 contains: 0
myArray element6 contains: 0
myArray element7 contains: 0
myArray element8 contains: 0

Multi-dimensional Arrays

Array of arrays

 

Declared by use of two or more sequential [square brackets]:

 

data type array Name[array size 1] [array size 2] ;

 

Akin to N rows & columns in a spreadsheet:

Column 0 Column 1 Column 2 Column 3
Row 0 arrayName[ 0 ][ 0 ] arrayName[ 0 ][ 1 ] arrayName[ 0 ][ 2 ] arrayName[ 0 ][ 3 ]
Row 1 arrayName[ 1 ][ 0 ] arrayName[ 1 ][ 1 ] arrayName[ 1 ][ 2 ] arrayName[ 1 ][ 3 ]
Row 2 arrayName[ 2 ][ 0 ] arrayName[ 2 ][ 1 ] arrayName[ 2 ][ 2 ] arrayName[ 2 ][ 3 ]

 

int myMultiArray[ 3 ] [ 4 ;  //declares a  two dimensional array called myMultiArray that contains 6 elements; e.g. in 3 rows / 4 columns

 

Defined by assiging values, separated by a comma, within {curly braces} for each dimension:

 

int myMultiArray[ 3 ] [ 4 ] = { { 0, 1, 2, 3 }, { 4, 5, 6, 7 }, { 8, 9, 10, 11 } } ; //same as:

int myMultiArray[ 3 ] [ 4 ] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 } ; //no need for nested curly braces

 

Single values can be defined by assigning the value to the specific element number, starting from zero for each dimension!

 

myMultiArray[ 2 ] [ 2 ] = 42 ; //sets the element in row 2, column 2 to 42

 

Specific elements can be accessed by assigning an array element to a variable

 

int myVar = myArray[ 1 ] [ 3 ] ; //assigns myVar with the element  contained in row 1, column 3

 

Compile & run:

Element [2][2] is: 10
Element [2][2] is now: 42
myVar has now been assigned the [2][2] element: 42

Character Arrays

Utilises the char data type followed by the chosen identifier and square brackets indicating the number of elements in the array:

 

char identifier[N] ; //array declaration

 

e.g.:    char myArray[7] ; //declaration of char array for 7 elements

 

Alternatively, if the number of elements in the array is ommited, the compiler will automatically size the array upon definition of the array contents.

 

e.g.:    char yourArray[] ; //declaration of char array for N characters

 

Values are assigned to the elements of a character array by using curly braces, and including a comma separated list of N 'single quoted' characters, where N is the number of elements indicated within the square brackets (which can be omitted to let the compiler automatically size the array):

 

e.g.:    char myCharArray[7] = {'L','a','v','e','r','d','a'} ;

 

or:    char myCharArray[] = {'L','a','v','e','r','d','a'} ;

 

 

As per numerical arrays, character arrays can also assign individual elements by index number. For example, say a character array is defined as follows: char myExample[] = {'D','i','v','e','r'} ; a specific character can be assigned like so: myExample[2] = 'n' ;

 

Compile & Run:

Element 0 of myCharArray: L
Element 1 of myCharArray: a
Element 2 of myCharArray: v
Element 3 of myCharArray: e
Element 4 of myCharArray: r
Element 5 of myCharArray: d
Element 6 of myCharArray: a 

 

yourCharArray contains: Benelli

 

Diner

C Strings

Having to use individually single quoted characters separated by a comma is quite clumsy, and therefore error prone, but thankfully there's a shorthand method of utilising a double quoted literal string of characters:

 

e.g. char myString[] = "Yamaha" ;

 

A string contained in double quotes is actually an array of constant characters, terminated with a null character '\0'. Thus the above double quoted string example consists of 8 characters including the null!

 

Compile & Run:

Yamaha

char Array Pointers

A string can be assigned to an array as follows

 

char arrString[] = "Saturn" ;

 

The compiler converts the string of literal characters in to an array, terminated with a NULL.

 

It is therefore possible to assign the string directly to a char pointer (which is in effect the same thing as above):

 

char *ptrString = "Titanium" ;

 

Both can be used in the same manner:

Compile & Run:

r
n
r
n
Saturn
Titanium

Pointer Arrays

Pointer arrays contain pointers to other data types, such as an int or char.

 

Declared as per a normal pointer, appended by the array subscript square brackets:

 

int *myPtr[N] ; //where N indicates the number of pointers required in the array

 

Compile & Run:

Array element [0] via pointer array: 10
Array element [1] via pointer array: 20
Array element [2] via pointer array: 30
Array element [3] via pointer array: 40
Array element [4] via pointer array: 50

 

 

Similarly, applied as a char pointer array to point to strings:

Compile & Run:

Array element [0] via pointer array: Debbie
Array element [1] via pointer array: Noko
Array element [2] via pointer array: Jimmy
Array element [3] via pointer array: Julia
Array element [4] via pointer array: Vanessa

C++ String class

C and C++ do not have a native string data type.

 

Instead they rely on a null terminated char array, and are initialised in C like so:

 

char chArr[] = "My new house" ;

 

char *ptrArr = "You should see my new house" ;

 

C++ has an alternative method of handling strings that uses the string class, thus creating a string object.

 

Requires the #include <string> preprocessor directive, allowing string to be used like any other data type.

 

Part of the std namespace, and therefore also requires the using namespace std ; preprocessor directive.

 

Declared / defined by simply using the string keyword:

 

string myString ;  //declaration

 

myString = "Hip Priests and Kamerads" ;  //definition

 

string yourString = "This Nation's Saving Grace" ;  //initialisation

 

string cppString("C++ string text goes in here") ;  //initialisation

 

The last example above sends a double quoted list of characters as the parameter to the string class, to create the string object containing the quoted characters.

 

Example using the .length() method of the string class:

Compile & Run:

Array element [0] contains: T
Array element [1] contains: h
Array element [2] contains: e
Array element [3] contains:
Array element [4] contains: a
Array element [5] contains: m
Array element [6] contains: a
Array element [7] contains: z
Array element [8] contains: i
Array element [9] contains: n
Array element [10] contains: g
Array element [11] contains:
Array element [12] contains: S
Array element [13] contains: p
Array element [14] contains: i
Array element [15] contains: d
Array element [16] contains: e
Array element [17] contains: r
Array element [18] contains: m
Array element [19] contains: a
Array element [20] contains: n
The amazing Spiderman

 

 

Example using the iterator, begin() and end() methods of the string class, and then dereferencing a pointer to access the individual characters within the string object:

Compile & Run:

Array element [0] contains: T
Array element [1] contains: h
Array element [2] contains: e
Array element [3] contains:
Array element [4] contains: G
Array element [5] contains: r
Array element [6] contains: e
Array element [7] contains: e
Array element [8] contains: n
Array element [9] contains:
Array element [10] contains: G
Array element [11] contains: o
Array element [12] contains: b
Array element [13] contains: l
Array element [14] contains: i
Array element [15] contains: n
The Green Goblin

String Methods

Requires the #include <string> preprocessor directive.

 

Part of the std namespace, and therefore also requires the using namespace std ; preprocessor directive.

 

Here are some of the more common string methods:

 

+, += Joins / Concatenates strings
<< Output Stream
==, !=, < <=, >, >= Compare strings
>> Input Stream
myString.append() Append string/characters
myString.assign("string-goes-here") Same as: myString = "string-goes-here" ;
myString.at(pos) Returns character at pos
myString.begin() Returns iterator positioned at first character of string. Start pointer
myString.c_str() Returns C string pointer. Null terminated
myString.capacity() Returns size of allocated storage for string
myString.compare(string2) Returns 0 if strings compare equal
constructors string strOne() = "string goes here" ;

string strTwo("string goes here") ;

string strThree ; strThree = "Anorak" ;

string strFour (strOne) ;

char *testStr = "testing" ; string strFive(testStr) ;

string strSix(testStr, 4) ; //first 4 characters of testStr

string strSeven(strOne, pos, len) ; //copy strOne into StrSeven at pos, for len

string strEight(len, 'x') ; //len number of 'x' characters

myString.copy(ptrArr, len, pos) Copies substring of len from myString from pos, into array at ptrArr

Doesn not append a NULL to ptrArr, needs to be carried out separately

myString.data() Returns C string pointer. NOT NULL terminated
myString.empty() Returns 1 if empty string, or 0 if not empty string
myString.end() Returns iterator positioned at last character of string. End pointer
myString.erase() Erases the string. No parameters required
myString.find(string2) Returns position of FIRST occurrence of string2
myString.find_first_not_of("char/string") Returns position of FIRST char/string NOT defined in the "char/string" parameter list
myString.find_first_of("char/string") Returns position of FIRST char/string defined in the "char/string" parameter list
myString.find_last_not_of("char/string") Returns position of LAST char/string NOT defined in the "char/string" parameter list
myString.find_last_of("char/string") Returns position of LAST char/string defined in the "char/string" parameter list
getline(input_stream, string, delim) Extracts chars from input stream and stores in string until .max_size(), EOF or delim
myString.insert(pos, string) Insert a copy of string into myString at position pos
myString.length() Returns int length of string. No parameters required
myString.max_size() Returns integer defining maximum size of string possible
myString.rbegin() reverse begin
myString.rend() reverse end
myString.rfind(string2) Returns position of LAST occurrence of string2
myString.replace(pos, len, string2) Replace len characters in myString at pos, with string2
myString.resize(len, 'char') Resizes myString to len. Truncates if less. Expands if smaller. If 'character' is missing, filled with blanks
myString.rfind("char/string") Returns position of LAST char/string defined in the "char/string" parameter list
myString.size() Returns int size of string. Same as above. No parameters required
myString.substr(pos,len) Returns substring within myString from pos, for len characters
myString.swap(string2) Swaps string2 with myString

 

String Input with getline()

cin stops reading from the input buffer when it encounters a space.

 

To overcome this, the getline(source, destination) ; function is used to read the input stream from the source and store it in the specified destination, until it encounters a newline \n character (created when the user presses return).

 

The cin.ignore() ; function is used to ignore any content left in the input buffer.

 

Compile & Run:

Please enter your full name:
Eva Mendes
Hi Eva
Please re-enter your full name:
Eva Mendes
Thanks Eva Mendes, nice to see you!

Vectors

Similar to arrays, but dynamically resizes as the program requires.

 

Elements start from 0.

 

Declared by using the vector keyword, then enclosing the data type with <angle brackets>, followed by the preferred identifier and size as follows:

 

vector <data-type> vecotor-name ( size ) ;

 

Or with an initial value: vector <data-type> vecotor-name ( size, initial-value ) ;

 

Requires the vector library and therefore must use the preprocessor directive: #include <vector>

 

This library also allows a number of vector functions.

 

To use a vector functions simply append the function required with the dot operator e.g. to find out the number of elements for a vector initialised like so: vector <char> cactus(5, 27) ;

 

cout << cactus.size() ; // would return a value of 5

 

Compile & Run:

myVec was initialised with 7 elements, the first being: 42, and is therefore Populated. 

 

Adding another element to the end has increased the size of the vector to 8 elements, and we can see that 63 is the last value!

 

Let's remove that last element, which reduces the vector size to: 7 and we can once again see that the final element is: 42

 

OK, enough of this myVec, let's clear it out and move on! myVec is now: 0

 

myVec.at(pos) Returns the value at pos
myVec.back() Returns the value in the final element
myVec.clean() Removes all elements
myVec.empty() Returns TRUE (1) if empty, or FALSE (0) otherwise
myVec.front() Returns the value in the first element
myVec.pop_back() Removes the final element
myVec.push_back(value) Adds the specified value at the end of the vector
myVec.size() Returns the number of elements  in the vector

Structures

User defined data type that groups of one or more variables, of potentially different data types, under a single identifier name, terminated with a semi-colon ;

 

Declared using the struct keyword like so:

 

struct identifier {

data type member-identifier ;
data type member-identifier ;

} ;

 

e.g.

struct bike {

int speed ;

float price ;

char *model ;

} ;

 

Once declared the structure can be used the same as any other data type:

 

e.g.

bike ducati ;

bike yamaha, honda ;

 

Alternatively a structure can be declared with objects after the closing } and before the ; as follows:

 

e.g.

struct bike {

int speed ;

float price ;

char *model ;

} ducati, yamaha, honda ; //three bikes structs declared

 

Values are assigned in a similar manner to arrays by use of the curly braces:

 

e.g.

ducati = { 145, 7655, "Monster" }

 

and can also be assigned within the struct declaration:

 

e.g.

struct bike {

int speed ;

float price ;

char *model ;

} ducati, yamaha = { 128, 5699, "FZR1" }, honda ; //three bikes structs declared, one of which is also initialised with values

 

 

Individual members are referred to by using the . dot member operator, which connects the structure name with the member name:

 

e.g.

ducati.speed

 

This allows individual structure members to be assigned values or return their values:

 

e.g.

honda.speed = 144 ;  //sets the speed member of the honda struct

cout << honda.speed ;  //gets the speed of the honda struct

 

 

Compile & Run:

Enter make: honda
Enter speed: 120
Enter price: 5699 

 

My bike is a Fantic with a top speed of 65mph costing £320

 

Your bike is a honda with a top speed of 120mph costing £5699

 

And let's not forget Hailwood's Ducati with a top speed of 185mph costing £27999

 

Or Agostini's MV Augusta with a top speed of 179mph costing £33864

 

 

 

(*Note: Unlike C, the keyword struct does not have to be used in the declaration of a new struct, as per line 19)

 


 

In C++ structures are quite similar to classes and can incorporate member functions. However, the default visibility of members within a structure is public, whereas they are private in a class.

 

Example of a structure with methods:

. and -> Member Access Operators

Access to members of Structures (and members of other object data types) is carried out using . dot notation, or by the shorthand little arrow -> member pointer dereferencing operator (aka member selection operator).

 

Given a structure:

 

struct rider {

char *team ;

int pos ;

} smith, marquez = { "Honda", 1 } ;

 

We can access the members using the . dot operator like so:

 

smith.team = "Monster Yamaha Tech 3" ; //set the team of the rider struct called smith

 

cout << marquez.team ;  //get the team of the rider struct called marquez

 

 

Alternatively, members of a struct can be accessed by member pointer dereferencing, carried out using the little arrow -> like so:

 

rider *ptr = &marquez ;  //first we define a pointer to the object

 

cout << ptr->team ;  //we can now use the -> to select the member

 

The -> dereferences the pointer and accesses the specified member.

 

*Note:  (*ptr).member is entirely equivalent to ptr->member, but is much easier to write.

 

Compile & Run:

Monster Yamaha Tech 3
Honda
Honda is in position 1
Monster Yamaha Tech 3 is in position 9

Unions

Unions are similar to structures but only one member within the union can be used at a time, due to it having a shared memory size for all members.

 

union identifier {

char desc[50] ;
float price ;
int devs ;
} ;

 

Unions are used when just one condition will be applied and only one variable is required.

 

Compile & Run:

The best OS might just possibly be fun, free and better! It costs less than $0.01 and has about 1200 developers on each release! 

A certain other consumer OS is generally restrictive, proprietary and monopolistic! It costs too much, i.e £99.99, and has around 1138 developers trying to make it work!

typedef structures

Isn't necessarily needed in C++, but has been included here for completeness.

 

In C, it provides a shortcut instead of having to write out the full syntax, e.g. struct myStruct { . . . } ;

 

Whereas in C++ typedef is implied, and therefore does not require the use of the keyword struct, thus saving a few more keystrokes and making the code look cleaner.

 

Syntax:

typedef struct identifier {

int memberOne ;

char memberTwo ;

float memberThree ;

} myStruct ;

 

myStruct can now be used instead of having to use the keyword, struct, before each declaration of a new structure.

 

Compile & Run:

Monster Yamaha Tech 3
Honda
Honda is in position 1
Monster Yamaha Tech 3 is in position 9

nested structures

Allows structures (i.e. one type of user defined data type) to be used within other structures.

 

Compile & Run:

Smith rides a Monster Yamaha Tech 3 and finished in position 9
Marquez rides a Honda and finished in position 1

Namespace

Provides a user defined scope.

 

Useful for objects/functions that are similarly named.

 

For instance, say two objects/functions had the same name, by using the concept of namespaces, we can specify which object/function we are explicitly referring to.

 

The keyword namespace is followed by a user defined identifier for the desired namespace, which then encapsulates the code for that namespace within { curly braces }

 

Syntax:

namespace namespace_identifier {

...bunch

...of

...code

}

 

 

To then call upon a specific object/function within a namespace the scope resolution operator is used, which consists of two colons ::

 

namespace_identifier::myFunc() ; //refers to the myFunc() function in the namespace_identifier namespace

namespace_identifier::myInt ; //refers to the myInt variable in namespace_identifier namespace

 

 

The keyword using directive allows the member of the namespace_identifier to be utilised from that point forward (or until it is redefined), on its own i.e. just using member, like so:

 

using namespace_identifier::member ;

 

Now, member can be used as though it had been declared within the current scope.

 

Alternatively, the keyword using followed by the keyword namespace and the namespace_identifier can be utilised to refer to all members of a specific namespace:

 

using namespace std ;

 

Now all members of the specified namespace can be utilised without further need for the scope resolution operator ::

 

Compile & Run:

5
10
15
20
25
Now in namespace myNameOne
Now in namespace myNameTwo
Now in namespace myNameOne
1
2
3
4
5

 

 

A namespace alias can also be declared by use of the keyword namespace followed by the preferred alias, which is assigned to the desired existing namespace - as per line 32 above.