A C++ Crash Course: UW Association For Computing Machinery
A C++ Crash Course: UW Association For Computing Machinery
Part I
The stack
Arrays (working model)
Pointers
A practice program
C-style types
Typedefs
Structs
C++ classes
Inheritance and dynamic dispatch
Memory management
The heap
Destructors
Advanced topics
Modifiers: const, static, and extern
Operator overloading
Templates
Goals of Java
Java, C, and C++, have different design goals.
Java
Simple
Consistent
Huge OO Focus
Cross platform via a virtual machine
Originally for embedded systems
C
Low level
No Runtime Type info
Easy implementation
C++
Originally to add some OO functionality to C
Attempt to be a higher-level language
Now its a totally different language
void printSum(void)
{
int x, y;
int sum = x + y;
int sum = x + y;
// print sum
// print sum
}
App
int sum = x + y;
// print sum
}
printSum()
}
class App {
public static void main(String[] args) {
Calculator c = new Calculator;
c.printSum();
}
}
Calculator
class Calculator {
public void printSum(void) {
int x, y;
int sum = x + y;
int sum = x + y;
// print sum
// print sum
}
}
class App {
public static void main(String[] args)
{
Calculator c = new Calculator;
c.printSum();
}
}
Procedural Programming
Functions are free-floating methods disassociated from
any class
Functions declarations can be separate from function
implementations
The declaration provides the signature, which specifies the
name, return type, and parameter list of the function
C is completely procedural
C++ mixes object-oriented and procedural programming
Discussion Point I
Which of these programs can be written
procedurally? Object-orientedly?
HelloWorld
A traffic simulator
Must simulate cars, roads, and the interactions between
these entities
A calculator
Accepts two numbers, then calculates the sum or
difference, depending on a user-selected operator
An mp3 player
Accepts a list of files, and plays them in the specified
order. Needs to support skins
pt
Point pt;
pt = new Point(3, 4)
p
moveToDiagonal(Point p) {
p.setY(p.getX());
}
int y)
d1
aFunc
y
x
x
main
Discussion Point II
Examine the code fragment below.
Draw the stack frame(s) for some sample input.
If you see any bugs, what are they? How would the
program behave?
void sillyRecursiveFunction(int i) {
if(i == 0) {
return;
}
else {
sillyRecursiveFunction(i 1);
}
}
Arrays
<ArrayType> arrayName[ numElements ]
Arrays are contiguous memory
locations, and its name refers
only to the address of the first
element
Indexing into an array is the
same as adding an offset to the
address of the first element
When declaring an array, its size
must be known at compile-time
myArray[5]
myArray[4]
myArray[3]
myArray[2]
myArray[1]
myArray[0]
or myArray
Pointers
What if we had variables that contained addresses?
They could contain addresses of anything!
We could use these
variables in functions to
modify the callers data
(we could implement
Javas parameterpassing semantics!)
x
(4104)
Variable
name
y
(4100)
n
(4096)
Address
Storage space
Pointers: vocabulary
A pointer is a variable
which contains
addresses of other
variables
Accessing the data at
the contained address
is called dereferencing
a pointer or following a
pointer
x
(4104)
y
(4100)
4096
n
(4096)
Pointer Syntax
Declaring Pointers
Using Pointers
Dereferencing a pointer:
*ptrName
Go to the address contained in the
variable ptrName
ptrName is a variable which
contains the address of
something of type <Type>
Getting the address of a variable:
&aVar
Get the address of aVar
Declaring a pointer:
<Type> * ptrName;
For example:
int * nPtr1, * nPtr2;
void aFunc(
int aParam,
int * ptrParam);
For example:
aFunc(myInt,
&anotherInt);
anInt = *myPtr * 4;
*dinner = 100;
Box Diagrams
ps type is int
pointer. qs type
is int.
Assign 5 to where
p points (which is
q).
p
Memory Layout
p contains the
address of an
int. q contains an
int.
Go to the address
that p contains, and
place a 5 there.
p (8200)
8196
q (8196)
Memory Layout
Box diagram
main
void doubleIt(int x,
int * p)
{
16
a
*p = 2 * x;
}
int main(int argc,
const char * argv[])
{
doubleIt
int a = 16;
doubleIt(9, &a);
x 9
return 0;
}
p
p
(8200)
8192
doubleIt
x
(8196)
a
(8192)
16
main
Pointer Arithmetic
Pointers are numbers, so you can do math on them!
int * p = &a;
p
(8200)
b
(8196)
a
(8192)
8192
9
16
*p = 200;
p
(8200)
b
(8196)
a
(8192)
8192
9
200
*(p+1) = 300;
p
(8200)
b
(8196)
a
(8192)
8192
300
200
*p
myArray[0]
*(p+0)
*myArray
p[0]
0[p]
myArray[4]
(9000)
myArray[3]
(8196)
myArray[2]
(8192)
myArray[1]
(8188)
myArray[0]
(8184)
p
(8180)
8184
Discussion Point IV
How do pointers and arrays differ?
Hint: how are pointers implemented in
memory? Arrays?
Exercise
Get up and stretch!
Do the worksheet exercise
Then, write a program to do the following:
Read some numbers from the user (up to a
max number of numbers)
Calculate the average value of those numbers
Print the users values which are greater than
the average
Pointer Problems
Pointers can refer to other variables, but:
Create an additional variable
Have an ugly syntax
Function Pointers
<ReturnType> (*ptrName)(arg type list );
p = bar;
p(2, b); // equivalent to bar(2, b);
(*p)(2, b); // Exactly the same
return 0;
}
References
References are an additional name to an
existing memory location
If we wanted something called ref to refer to a variable x:
Pointer:
x
ref
Reference:
9
x
ref
Properties of References
Reference properties:
Cannot be reassigned
Must be assigned a referee at construction
Therefore:
References cannot be NULL
You cannot make an array of references.
Given what you know about references, can you
explain where these properties come from?
Reference Syntax
References
Pointers
Declaring a reference:
<Type> & refName =
referee;
Declaring a pointer:
<Type> * ptrName;
Usage:
int n;
int & referee = n;
void aFunc(
int aParam,
int & ptrParam);
Usage:
int n;
int * nPtr1 = &n;
void aFunc(
int aParam,
int * ptrParam);
aFunc(1, n);
aFunc(1, &n);
Discussion Point V
What are the differences between Java
references and C++ references? What
about Java references and C++ pointers?
C-style struct
A struct is used to group related data items
struct student {
int id;
char name[80;]
};
To the programmer
id and name are now related
struct student creates a convenient grouping
To the compiler
Id and name have a fixed ordering (not offset) in memory
Struct student is a first-class type that can be passed to functions
struct Syntax
Declaring a Struct
Declaring a struct:
struct [optional name] {
<type> field1;
<type> field2;
} [instance list];
Examples:
struct Foo {
int field1;
char field2;
} foo,*foo_ptr;
enum
An enum creates an enumerated type; they
are options with an associated value
enum PrimaryColors {
RED = 0,
GREEN,
BLUE
};
enum Syntax
Declaring an enum
Declaring a enum:
enum [optional name] {
OptionName [= int],
OptionName [= int],
} [instance list];
Example of an enum:
enum Color {
RED,
GREEN,
BLUE
} color, *color_ptr;
enum Color c;
void drawCircle
(enum Color c);
Enum quirks
Problems with Enums:
Frail abstraction
Treated as integers
Can be assigned invalid values
Flat namespace
Proper use guidelines:
Avoid breaking abstraction
Mangle name of enum into option
name (so ColorRed instead of Red)
Here is one sanctioned abstraction break
enum Color {
RED,
GREED,
BLUE,
NumberOfColors
};
union
An union creates an union type; all fields
share the same memory location
union Argument {
int intVal;
double doubleVal;
char charVal;
};
union Syntax
Declaring an enum
Declaring a enum:
union [optional name] {
<type> name1;
<type> name2;
} [instance list];
Example of a union:
union Argument {
int value;
char *string;
} arg1, *ptr;
union Argument arg2;
arg1.value = 3;
arg2.string = NULL;
Union quirks
Problems with Enums:
Only assume that the last field
written two is valid.
Dont use to save space.
Proper use guidelines:
Ensure you have another method
of knowing which field is currently
valid.
Typedef
Typedef is used to create an alias to a type
typedef
unsigned char
unsigned char mybyte;
byte mybyte;
byte;
Clarification
More informative names for a type be given
Variables that use the same type in different ways can
be separated easily
Convenience
Type names can get very long
People like structs to look like real types
Some type names (like function pointers or array
pointers) are really hard to read/write
Typedefs structs/enums/unions
People often make a typedef of an
anonymous struct, enum, or union
typedef struct {
int id;
char name[80];
} Student;
struct Student {
int id;
char name[80];
};
Student st;
struct List {
int data;
struct List *next;
};
Discussion Point VI
What advantages do named
structs/unions have over anonymous
ones? Are enums different?
How would you try to pass anonymous
structs, enums, or unions to a function? Can
you?
C++ Gotcha I
Dont use exceptions unless you
know what youre doing!
Uncaught C++ exceptions do not produce a stack trace.
C++ does not automatically reclaim newd resources
(more in a later tutorial)
void someFunc(void) {
throw Exception!";
}
int main(int argc,
const char * argv[]) {
someFunc();
return 0;
}
$ ./myProg
Aborted
$
C++ Gotcha II
Dont return pointers (or references) to
local variables!
double * aFunc(void) {
double d;
return &d;
}
int main(int argc,
const char * argv[]) {
double * pd = aFunc();
*pd = 3.14;
return 0;
}
Boom! (maybe)
i = new int;
} else if( anotherCondition ) {
i = new int;
Does the phrase null
}
*i = someVariable;
pointer exception
sound familiar?
C++ Gotcha IV
Never use an array without knowing its size
C++ arrays do not
know their own size.
Always pass a size
variable with the array
Always check the
bounds manually (C++
wont do it for you!)
int myArray[5];
myArray[0]
myArray[1]
myArray[2]
myArray[3]
myArray[4]
=
=
=
=
=
85;
10;
2;
45;
393;
myArray[5] = 9;
myArray[-1] = 4;
No Error! Undefined Behavior!
What We Covered
The procedural programming paradigm
Functions and parameter passing
The C/C++ memory model Part I (the stack)
Pointers
Arrays
C++-style References
C type constructs
Structs, enums, unions, typedefs
Any questions?
Nathan Ratliff
Version 1 of the C++ tutorial
Doug Zongker
Version 1 of the handouts
Pointers to Arrays
int (*ar)[3]
vs.
int *ar[3]
int a[3];
int *p = a;
p+1 == 8188
int (*p2)[3] = &a;
p2+1 == 8196
(*p2)[0] == p2[0][0] == 122
(*(p2+1))[0] == p2[1][0] == p2 == 8184
p
(8200)
p2
(8196)
&a[2]
(8192)
&a[1]
(8188)
&a[0]
(8184)
8184
8184
16
485
122