Built-In (a.k.a. Native) Types in C++ int, long, short, char (signed, integer arithmetic) unsigned versions too unsigned int, unsigned long, etc. C++ guarantees a char is one byte in size Sizes of other types are platform dependent Can determine using sizeof() , <climits> INT_MAX float, double (floating point arithmetic) More expensive in space and time Useful when you need to describe continuous quantities bool type Logic type, takes on values true, false
User (& Library) DefinedTypes in C++ (unscoped or scoped) enumerations enum primary_color {red, blue, yellow}; // scoped enums are preferred as of C++11 enum struct palette {ochre, umber chartreuse, ecru}; functions and operators For example, things called from main function structs and classes Similar abstractions in C++, extend C structs
Comparing C++ Classes and Structs struct My_Data { My_Data (int i) : x_(i) {} int x_; }; class My_Object public: My_Object (); ~My_Object (); private: int y_; Struct members are public by default Class members are private by default Both can have Constructors Destructors Member variables Member functions Common practice: use structs for data use classes for objects with non-trivial methods
More About Both Native and User Types Pointers raw memory address of an object or variable its type constrains what types it can point to (more later) can take on a value of 0 (not pointing to anything) References “alias” for an object or variable its type constrains what types it can refer to (more later) cannot be 0 (always references something else) Mutable (default) vs. const types (read right to left) const int i; // read-only declaration int j; // readable and writable declaration
Scopes in C++ Each symbol is associated with a scope The entire program (global scope) A namespace (namespace scope) Members of a class (class scope) A function (function scope) A block (block scope) A symbol is only visible within its scope Helps hide unneeded details (abstraction) Helps prevent symbol conflicts (encapsulation)
Pointers Often need to refer to another object Two ways to do this Without making a copy of the object itself Two ways to do this Indirectly, via a pointer Gives the address of the object (analogy: street address) Requires the code to do extra work: dereferencing Like going to the given address, to talk to the person Directly, via a reference Acts as an alias for the object Code interacts with reference as if it were object itself
What’s a Pointer? A variable holding an address Can be untyped Of what it “points to” in memory Can be untyped E.g., void * v; // points to anything However, usually they’re typed Checked by compiler Can only be assigned addresses of variables of type to which it can point E.g., int * p; // only points to int Can point to nothing E.g., p = 0; // or p = nullptr; (C++11) Can change where it points As long as pointer itself isn’t const E.g., p = &i; // now points to i int i 7 0x7fffdad0 int *p
What’s a Reference? Also a variable holding an address Of what it “refers to” in memory But with a nicer interface A more direct alias for the object Hides indirection from programmers Must be typed Checked by compiler Again can only refer to the type with which it was declared E.g., int & r =i; // refers to int i Always refers to (same) something Must initialize to refer to a variable Can’t change what it aliases int i 7 0x7fffdad0 int & r
Untangling Operator Syntax Symbol Used in a declaration Used in a definition unary & (ampersand) reference, e.g., int i; int &r = i; address-of, e.g., p = & i; unary * (star) pointer, e.g., int * p; dereference, e.g., * p = 7; -> (arrow) member access via pointer, e.g., C c; C * cp=&c; cp->add(3); . (dot) member access via reference or object, e.g., C c; c.add(3); C & cr = c; cr.add(3);
Aliasing and References int main (int argc, char **argv) { int i = 0; int j = 1; int & r = i; int & s = i; r = 8; // i is now 8, j is still 1 } An object and all the references to it alias the same location E.g., i, r, and s Assigning a new value to i, r or s changes value seen through the others But does not change value seen through j int & r 0xefffdad0 8 int i 0xefffdad0 1 int j int & s
Aliasing and Pointers Distinct variables have different memory locations E.g., i and j A variable and all the pointers to it (when they’re dereferenced) all alias the same location E.g., i, *p, and *q Assigning a new value to i, *p or *q changes value seen through the others But does not change value seen through j int main (int argc, char *argv[]) { int i = 0; int j = 1; int * p = & i; int * q = & i; *q = 6; // i is now 6, j is still 1 } int *p 0xefffdad0 6 int i int *q 0xefffdad0 1 int j
References to Pointers int main (int argc, char **argv) { int j = 1; int & r = j; // r aliases j int * p = & r; // p really // points to j int * & t = p; // t aliases p } Can’t have a pointer to a reference But can point to what the reference aliases Address-of operator on a reference to a variable Gives address of variable … not of reference itself Reference to a pointer An alias for the pointer … not for what it points to Useful to pass a pointer to code that may change it int & r 0xefffdad0 1 int j 0xefffdad0 int * p int * & t 0xefffdad0
References to Const Remember: references must refer to something Can’t be nil Also, once initialized, they cannot be changed E.g., can’t redirect t to i Const with a reference A promise not to change what’s aliased E.g., can’t use t to change j Can’t use reference to non-const with a const variable, but reverse is ok int main (int argc, char **argv) { const int i = 0; int j = 1; int & r = j; // r can’t refer to i const int & s = i; // ok for s,t const int & t = j; // to alias i,j }
Const Pointers and Pointers to Const Read declarations right to left Make promises via the const keyword in pointer declaration: not to change where the pointer points not to change value at the location to which it points Can (only) change Where w points and the value at the location to which it points The value at the location to which x points Where y points A pointer to non-const cannot point to a const variable neither w nor x can point to i any of them can point to j int main (int argc, char **argv) { const int i = 0; int j = 1; int k = 2; // pointer to int int * w = & j; // (array names are like const // pointers to their 0th position) // const pointer to int int * const x = & j; // pointer to const int const int * y = & i; // const pointer to const int const int * const z = & j; }
Passing Parameters to Functions By value Makes a copy e.g., of value of h into local variable a E.g., ++a changes a not h By reference Alias for passed variable E.g., c = b changes j but you can’t change b (or i): const Can pass pointer by value And then use pointer to change location it aliases E.g., *d = c changes k but ++d changes where d points int main (int argc, char **argv) { int h = -1; int i = 0; int j = 1; int k = 2; return func (h, i, j, & k); } int func (int a, const int & b, int & c, int * d) ++a; c = b; *d = c ++d; return 0;
A Few More Type Declaration Keywords These become increasingly important as we move into advanced topics like templates, generic programming The typedef keyword introduces a “type alias” E.g., for the type of a variable that points to another type typedef Foo * Foo_ptr; // Foo_ptr is alias for Foo * Foo_ptr p = 0; Foo * q = 0; // types are equivalent The auto keyword asks compiler to take a variable’s type from the type of expression used to initialize it E.g., auto y = m * x + b; // gets both type and value Use the decltype keyword if you want compiler to infer variable’s type but you don’t want to initialize it E.g., decltype(m * x + b) y; // gets type but not value