390 likes | 474 Views
CS 31 Discussion, Week 10. Faisal Alquaddoomi, faisal@cs.ucla.edu Office Hours: BH 2432, F 12:30-1:30pm. Whirlwind Overview of C++. Basic Program S tructure Variables, Types, Operators Control Structures Functions, parameters, return types Arrays, 1D and 2D Pointers, Dynamic Memory
E N D
CS 31 Discussion, Week 10 Faisal Alquaddoomi, faisal@cs.ucla.edu Office Hours: BH 2432,F 12:30-1:30pm
Whirlwind Overview of C++ • Basic Program Structure • Variables, Types, Operators • Control Structures • Functions, parameters, return types • Arrays, 1D and 2D • Pointers, Dynamic Memory • Structs, Classes, Methods, and Access Protection
Basic Program Structure • Should look familiar by now: #include <iostream> using namespace std; int main() { cout << “Hello, world!” << endl; return 0; }
Values, Variables, and Types • A value is a discrete manipulable entity, like 3 or ‘A’ • has a type, e.g. 3 is an integer and ‘A’ is a char • A variable is a named location to put a value • Variables have a type that defines what kinds of values they can hold • type of the value and the type of the variable must match in order to assign the value to the variable • Variables are first declared, then they can be used int x; // this is a declaration x = 3; // this is a use of the previously-declared variable
Kinds of Types • Intrinsic/primitive types: int, float, double, bool, char • Pointer types: int*, float*, double*, bool*, char*, etc. • Note that char* is a special case; it’s a c-string • Compound types: arrays • Arrays are just pointers to the first element of a series of variables in memory • Structured types: structs, classes • Common classes: string
Expressions and Operators • Expressions are combinations of values and operators which resolve to a final value • 3+6*12-2 is an expression, for instance • In C/C++, variables always have a value, so all expressions can be resolved, where resolved means reducing them to a single value • Operators take operands and performs an operation on them, resulting in a new value • 3+6 (+ with two operands, 3 and 6, both integers) => 9, an integer • Most of the time, types get “upcast” when involved with a larger type, e.g. 3 + 3.0 => 6.0, a double • When a variable appears in an expression, the value which it was last assigned is used in its place • except in the special case of & and *
Common Operators and Their Types • Arithmetic: +, -, *, / • mostly take numbers, result in the “larger” type of the operands • Boolean Comparison: >, <, >=, <=, !=, == • mostly take comparable values, result in a boolean value (true or false) • Boolean Conjunction: &&, ||, ! • take booleans, result in a boolean value • Assignment: = • resolves to the type (and value!) of the thing that was assigned, but avoid using in an ‘if’
Less Common Assignment Operators • Note that = is not the same thing as == • The first is assignment, and needs a variable to be on its left and a value to be on its right • The second is the comparison operator, and returns true if its operands are the same • In-place assignment: +=, -=, *=, /= • Pre/post-increment: x++, ++x, x--, --x • if it comes after, it means that first the value of the variable is used in the expression, then it’s changed • if it’s on its own line, x++; and ++x; do the same thing
Control Structures • Outside of just doing math and printing stuff, it’s useful to be able to control the program • ‘If’ is the fundamental control structure • ‘switch’ is a limited version of an ‘if-else if’ chain if (<boolean predicate>) { // go here if the predicate is true } else if (<boolean predicate>) { // go here if this predicate is true, // but the first one was false } else { // go here if nothing else matched }
Control Structures Cont’d • Iteration structures allow commands to be repeated continuously • Variants: for, while, do-while • all are equivalent, and can be rewritten from one to the other • do-while will always execute at least once inti = 0; while (i < 100) { // do something here i++; } for (inti = 0; i < 100; i++) { // do something here}
Functions, Parameters, Return Values • Functions allow common code to be combined and reused • Like variables, a function must be defined before it can be used • Functions have a name, a list of parameters, and a return type • the return type can be void, which means the function returns nothing • void functions cannot be used as values; they can only be called • Functions are called by using their name, and specifying a list of values to fill in the parameter • the program keeps track of where it was and jumps to execute the function, returning back where it left off with the return value when the function is done • the parameters of a function are typed; in order to call a function, you must specify values that have the same types, called the arguments • Example: bool raining = checkRain(6,7,2013);
Means of Passing Parameters • By default, functions take their parameters as pass-by-valueparameters • the parameter is a local variable inside of the function; the argument’s value is copied into the local variable • A parameter can be specified as pass-by-reference using an ampersand • allows modifications to the parameter to be reflected in the variable that was passed as an argument • arguments for a pass-by-reference parameter *must* be variables; a value cannot be modified
Return Values vs. Side Effects • Functions return a final value via the return <value>; keyword • the value that’s returned must match the return type of the function, specified in its definition • returning causes the function to end immediately • void functions can simply use return; • Additionally, functions can cause things to happen • modifying pass-by-reference parameters, printing stuff to the console, etc. • these are called side effects and are unrelated to the return type or value • void functions are generally useful because of side effects
Arrays: Sequences of Variables • An arrayis a series of variables of the same type, where each variable can be referred to by an index • an array can be of any type: primitives like int, compounds like structs and classes, even other arrays (which is essentially what a 2D array is) • When an array is declared, the number of indices it has is declared as well:intarr[10]; // has 10 slots, numbered 0-9 • Arrays are convenient for dealing with lots of data, since they can be iterated over and passed around to other functions as a set
Array Allocation, Initialization • Allocated Uninitialized:int x[100]; • Statically initialized with length specified:int y[5] = { 1, 2, 3 }; // only first three are filled • Statically initialized with length inferred:int z[] = { 100, 200, 300, 400 }; • You can always initialize an array after you declare it, e.g.:for (inti = 0; i < 100; i++) { x[i] = 100-i; }
Arrays and Functions • A function takes an array parameter like so:void myFunc(intarr[]) { /* stuff here */ } • Assume we have int bees[20]; we could call myFunc() like so:myFunc(bees); • Changes to arr inside of myFunc() will be reflected in bees, since arrays are always passed by reference • You can prevent the modification of an array by using const, e.g.:void myFunc(constintarr[]) { /* can’t change arr */ }
Array Special Case: C-Strings • Since arrays of chars are commonly used to represent text (remember, chars == letters), they have some special notation • char str[] = “Hi!”; is the same thing aschar str[] = {‘H’, ‘i’, ‘!’, ‘\0’}; is the same aschar str[] = {72, 73, 33, 0}; • Note the presence of the nul-terminator, a special character (== 0) that tells us when we’re at the end of the char array • without it, we’d have to pass the length of the array along whenever we used a function, which would be tedious • all the library functions for c-strings expect there to be a nul-terminator at the end of their arguments
Array Pitfalls • Assume arrays char A[5]; and char B[5]; • You can’t copy one array’s contents into another using assignment:A = B; // wrong • You can’t compare two arrays’ elements directly, either:if (A == B) { // wrong as well • You can’t directly concatenate two arrays’ elements together:A = A + B; // nope :( • For character arrays with nul-terminators (e.g. an element at the end that’s a zero), use strcpy(), strcmp(), strcat(), etc.
2D Arrays • Example: int beehive[20][50]; • Consists of 20 rows, each of which contain 50 integer slots • Elements are accessed like so:beehive[2][5] = 32; • In order to pass a 2D array to a function, you must specify all but the first dimension in the parameter, e.g.:void myFunction(int beehive[][5]) { /* … */ }
The Reference Operator, & • All variables live somewhere in memory • the place where they live is called their address • You can find a variable’s address using the reference operator &, ex:cout << (int)&x << endl; // prints where x lives • The & operator produces values of a special type, the “address type” • when used on an int, the type is int*, when used on a double, it’s double*, etc. • Since it’s a type, it needs a corresponding variable to store its value
Pointers • A pointer is simply a variable that happens to be of an “address type”, meaning that it can store addresses, ex:int* p; // points at some random address • A pointer can be set to point at a specific address:p = &x; // now p has the value of x’s address • The address type works with most of the arithmetic operators • When they’re applied, the result is an address • p += 5 moves p 5 integer-sized steps forward in memory from where it was previously pointing
The Dereference Operator, * • Addresses have a special operator, the dereference operator ‘*’, that allows the address to be converted back into a variable • Used for both getting and setting the value at the address • Example: (assume int* p = &x; where x is an int)*p = 32;// sets the address to which p points to 32// now x’s value is 32
Pointers and Arrays • An array is actually a pointer to the address of the first element of the series of values that make up the array in memory:int dogs[3]; // dogs has the value &dogs[0] • void myFunc(intarr[]); is equivalent tovoid myFunc(int* arr); • It can be useful to walk through an array with a pointer, e.g.:char str[] = “Howdy”; char* p = str;while (*p != ‘\0’) { cout << *p << endl; p++; }
Pointers and Arrays Cont’d • The familiar bracket operator is actually a bit of pointer arithmetic:intarr[200];arr[7] = 32;// is the same as…*(arr+7) = 32;// arr+7 produces the address 7 integer-steps// past arr, which is the start of the array.// then, that value is dereferenced// and 32 is stored into that slot in the array.
Pointers and Function Parameters • Pointers are passed like any other argument, e.g.:void myFunction(int* p) { *p = 100; }// ^ changes the thing which p points to • The const keyword disallows changing the reference • useful to get the efficiency of using a pointer without the danger of it changing the original thing; also applicable to & • example:void myFunction(constint* p) { *p = 100; // wrong!}
Pointers and Dynamic Memory • Data (that is, variables) can live in two places: • on the stack (i.e. local variables, managed for you) • on the heap (have to manage them yourself) • The advantage to using dynamic memory is that you can keep it around even when the function it was acquired in is done • not so with local variables, which are gone when the function that defined them ends • Pointers can store addresses to either location, stack or heap
Dynamic Memory Management • Acquire dynamic memory using the new keyword, e.g.:int* p = new int; // any type will do// ^ note that new returns an address • Once you have a handle to it (i.e. a pointer that’s set to the memory), you can manipulate it:*p = 3210; // sets the location in the heap • But you must always be sure to eventually free the memory you allocate using delete:delete p; // deletes what p points to, not p itself
Dynamic Memory Details • Very convenient for creating arbitrarily-sized arrays:int* getArray(intlen) {int* p = new int[len]; // <- only w/new return p;} • delete and new can be used in conjunction to resize an array:int* p = new int[20]; // assume this had data in it…int* bigger = new int[50]; // our new, bigger home // copy everything over… for (inti = 0; i < 20; i++) {bigger[i] = p[i]; } delete p; // don’t forget to free the old 20 bytes p = bigger; // now you can use your new, larger p
Structured Types • Structs allow you to collect differently-typed variables into a single unit, like a blueprint • Instances of structs can be created from this “blueprint”, each of which has all the variables in the definition (called fields) • Fields are accessed via the ‘.’ operator, e.g.:struct Coordinate { int x, y; }; // <- note the ; Coordinate homebase; // create instancehomebase.x = 15; // set fields…homebase.y = 12; // …again… // …now homebase holds 15, 12
Pointers to Structs and the Arrow Operator • Like all other types, each struct you create has an associated pointer type • Going with the previous coordinate example:Coordinate* p = new Coordinate;cout << (*p).x << “, “ << (*p).y << endl; • As a shorthand, you can do a ‘deref-and-field-access’ using the arrow operator, ‘->’:cout << p->x << “, “ << p->y << endl;
Classes • A class is a lot like a struct; it has fields, except they’re called members • A class also contains methods, which are functions that, in a sense, belong to the class • the functions are declared in the class definition, but can either be defined “inline” (i.e. in the class definition) or elsewhere in your code using the scope operator, :: • When you create an instance of a class and call a method on it, it’s implied that the method is acting on the instance that you passed it • in fact, there’s a “hidden parameter” called this that every method is passed; it points to the current instance on which the class is called
A Basic Class class Coordinate { private: int x, y; public: // inline functions intgetX() const { return x; } intgetY() const { return y; } void printCoords() const; }; void Coordinate::printCoords() { cout << x << “, “ << y << endl; }
Access Protection • Note the “private:”, “public:” specifiers • Everything after private, but before public, is accessible only from within the class’s method • Both members and methods can be private; private methods can only be called from other methods, not from outside of the class • Public members/methods can be accessed by anyone • There’s also “protected:”, but you don’t need to worry about that one for this class • Your constructors and destructors will always be public (which we’ll talk about in a moment…)
Constructors • Note that x and y are private, meaning that nothing but the class’s methods can directly access them • and note that none of them allow the members to be set! this class is somewhat useless… • If we want our class to never be changed, we at least need to provide some mechanism to set it up with useful values • Enter the constructor
A More Refined Class class Coordinate { private: int x, y; public: Coordinate(); Coordinate(int x, int y); // (other functions omitted) }; Coordinate::Coordinate() { x = 0; y = 0; } // note the lack of a return type // and that the name matches the class Coordinate::Coordinate(intx, inty) { this->x = x; this->y = y; }
Using the Class • Like structs, we can create instances of our class:Coordinate home(5, 8); // x = 5, y = 8 • We can call its methods, too:cout << home.getX() + home.getY() << endl;home.printCoords(); • Note that the arrow operator -> works for pointers to classes, too:Coordinate* p = new Coordinate(12,14);p->printCoords();delete p; // and get rid of it
Destructors • Declared the same way as a constructor, except with a tilde (~) in front of the name • destructors can’t take arguments, either, since they’re invoked automatically • Executed when an instance is destroyed • either by the local variable being destroyed • …or by the ‘delete’ keyword being used on an instance • Not required (constructors aren’t either, for that matter), but useful for cleaning up dynamic memory, etc.
The Class, Destructor’d class Coordinate { private: int x, y; public: ~Coordinate(); // (other functions omitted) }; // note the lack of a return type // and that the name matches the class Coordinate::~Coordinate() { cout << “Goodbye!” << endl; }
Review(Yes, it’s the same slide) • Basic Program Structure • Variables, Types, Operators • Control Structures • Functions, parameters, return types • Arrays, 1D and 2D • Pointers, Dynamic Memory • Structs, Classes, Methods, and Access Protection