580 likes | 723 Views
C++ crash course. Class 4 arrays, pointers, functions. Agenda. Boolean Logic Arrays and Pointers redux Functions Class functions Constructors Finishing the bookstore. Boolean Logic. Computers deal in 1 ’ s and 0 ’ s Many times we want to make decisions in terms of logic
E N D
C++ crash course Class 4 arrays, pointers, functions
Agenda • Boolean Logic • Arrays and Pointers redux • Functions • Class functions • Constructors • Finishing the bookstore
Boolean Logic • Computers deal in 1’s and 0’s • Many times we want to make decisions in terms of logic if( am_hungry AND like_apples) { eat_apple; }
Boolean Logic • C++ (like many other languages) allows you to do this using logical operators • These are binary operators, meaning they operate on two operands (the quantities on either side) • Results in a bool-type expression && logical and || logical or ! logical not == tests equality != tests non-equality <, >, <=, >= comparison operators operate on bool-type expressions only can operate on many types
Boolean Logic • How do we understand these operators? • Bool-expressions are either TRUE or FALSE • &&, ||, ! all change these values
Arrays • We started talking about these yesterday • Contiguous allocation in memory, accessed by pointers • Arrays are a compound type • Need: type specifier, identifier, dimension (must be known at compile-time) const unsigned buf_size = 512, max_files = 20; int staff_size = 27; const unsigned sz = get_size(); //ok char input_buffer[buf_size]; string fileTable[max_files + 1]; int vars[12]; // this works, but is bad practice // don’t hardcode except in consts //bad double salaries[staff_size]; int test_scores[get_size()]; int vals[sz];
Arrays • When we initialize an array, we can provide an initialization for each element • Otherwise, arrays will be initialized as they are in vectors – default variable initializers const unsigned array_sz = 3; int ia[array_sz] = {0,1,2}; const unsigned array_sz2 = 5; int ia2[array_sz2] = {0,1,2}; // this results in {0,1,2,0,0}; • Character arrays are special, and can be initialized with character string literals char ca1[] = {‘C’, ‘+’, ‘+’}; // note: no null terminator! char ca2[] = {‘C’, ‘+’, ‘+’, ‘\0’}; // null terminated char ca3[] = “C++”; // automatically null-terminated; equivalent // to the previous line
Arrays • Can’t initialize arrays with other arrays! int ia[] = {0,1,2}; // OK int ia2[](ia); // bad int ia3[3]; // ok, but uninitialized elements ia3 = ia; // bad • Arrays CANNOT get bigger once they’ve been created • Some compilers will let you do it anyway as a compiler extension, but you’re not guaranteed this
Arrays • Operators • The size of an array is type size_t • No size function; should be set as a const somewhere though • Subscript operator can change elements (a[n]) • Unlike in other languages, it is PERFECTLY LEGAL to access an array element outside of the size of the array! • Don’t do this: you’re messing with memory you shouldn’t be. Always check your array size before access.
Arrays • get_size() takes no arguments and returns an int • Which of these are legal definitions? unsigned buf_size = 1024; (a) int ia[buf_size]; (b) int ia[get_size()]; (c) ia[4 * 7 – 14]; (d) char st[11] = “fundamental”;
Arrays • Which of these definitions are illegal? (a) int ia[7] = {0,1,1,2,3,5,8}; (b) vector<int> ivec = {0,1,1,2,3,5,8}; (c) int ia2[] = ia1; (d) int ia3[] = ivec;
Pointers • Pointers can also be used for array access • We saw this yesterday • Pointers are compound types • Pointers are the iterators for arrays • Iterators can only be used for a specific container • Pointers can point to any kind of variable
Pointers • * is the dereference operator • in a variable definition, this indicates that the variable is a pointer • & is the address-of operator • tells us the address of a variable • Remember this from references? In a reference, instead of setting the value of a variable when it’s declared, we set its address – this is why references are bound once they’re initialized
Pointers • We can iterate through an array like so: constsize_tarray_sz = 4; intia[array_sz] = {0,1,2,3}; for(int *ptr = ia,size_tctr = 0; ctr < array_sz; ptr++, ctr++) cout << *ptr; • Why did we need the counter?
Pointers • As mentioned, we can point to anything vector<int> *pvec; int *ip1, *ip2; string *pstring; double *dp; double dp, *dp2; // only dp2 is a pointer here
Pointers • You can also write: string* ps1, ps2; • …but that can be confusing, since only ps1 is getting defined as a pointer
Pointers • As always, make sure you initialize your pointers! • Pointers only hold addresses in memory • Just like when we fail to initialize ints or other types with no default constructor (usually basic types), pointers will try to interpret whatever’s in memory at the point it’s been assigned as the address it should be pointing to • If you don’t know where to point your pointer, point it at 0 – that way you can find out if it’s been initialized
Pointers • Initialization can happen in four ways: • Constant expression with value 0 • Address of an object that is of the right type • Address one past the end of an object • Another pointer of the same type
Pointers • Which of these are okay? intival; int zero = 0; constintc_ival = 0; int *pi = &ival; pi = zero; pi = c_ival; pi = 0;
Pointers • If you’re using the <cstdlib> header, you can also use NULL • contains the line #define NULL 0 …which tells the preprocessor to interpret any place in the program that has the word NULL as being 0 • If you try to dereference a null pointer, you will get a Segmentation Fault
Pointers • There’s also void pointers, which can hold the address for any kind of type double obj = 3.14; double *pd = &obj; int myint = 3; void *pv = &obj; pv = pd; pv = &myint;
Pointers • We have pointers so we can operate on the objects they point to string s(“hello world”); string *sp = &s; cout << *sp; • This dereferences the pointer
Pointers • Which of the following are legal definitions? (a) int *ip; (b) string s, *sp = 0; (c) inti; double *dp = &i; (d) int *ip, ip2; (e) constinti=0, *p = i; (f) string *p = NULL;
Pointers • Assigning through pointers string s1(“some value”); string s2(“another value”); string *sp1 = &s1; string *sp2 = &s2; *sp1 = “a new value”; cout << s1 << endl << s2 << endl; sp1 = sp2; *sp1 = “a new value”; cout << s1 << endl << s2 << endl;
Pointers (to pointers) • Since pointers are also objects, we can point to them too intival = 1024; int *pi = &ival; int **ppi = π (Is your head exploding yet?)
Pointers • What does this program do? inti = 42, j = 1024; int *p1 = &I, *p2 = &j; *p2 = *p1 * *p2; *p1 *= *p1;
Pointers and Arrays • Yesterday we looked at iterator arithmetic • Pointer arithmetic is much the same intia[] = {0,2,4,6,8}; int *ip = ia; ip = &ia[4]; ip = ia; int *ip2 = ip+4; // equivalent to &ia[4];
Pointers and Arrays • We can dereference an expression int last = *(ia + 4); // refers to the 4th value // in the array last = *ia + 4; // adds 4 to the 0th value // in the array
Pointers and Arrays • Subscripting an array and subscripting a pointer are effectively the same operation int *p = &ia[2]; int j = p[1]; // 1 int in front of where p is int k = p[-2]; // 2 ints behind where p is
Pointers and Arrays • Another way to write the for loop we used earlier const size_t arr_sz = 5; int int_arr[arr_sz] = {0,1,2,3,4}; for (int *pbegin = int_arr, *pend = int_arr + arr_sz; pbegin != pend; pbegin++) cout << *pbegin << ‘‘;
Pointers • Where is p1 after this line of code? • p1 and p2 are both int pointers somewhere in the same array p1 += p2 – p1;
Pointers • We can make pointers to objects for types we create • There’s a special operator, ->, for accessing public members of those objects • Shorthand for (*ptr). Sales_item item1, item2; Sales_item *pitem = &item1; pitem->same_isbn(item2); (*pitem).same_isbn(item2);
Pointers and const • Pointers to const objects should not be able to change them • Pointers to const objects must use the const keyword const double mydbl = 17.0; const double mydbl2 = 43.0; double nonconst = 25; const double *cptr = &mydbl; // ok cptr = &mydbl2; // also ok: the ptr isn’t const
Pointers and const double dval = 3.14; const double *cptr = &dval; dval = 3.14159; *cptr = 3.14159; double *ptr = &dval; *ptr = 2.72; cout << *cptr;
Dynamic Arrays • We said that arrays have fixed size • Not completely true; it’s possible to create dynamically-sized arrays int *pia = new int[10]; // array of 10 // uninitialized ints int *pia = new int[10] (); // array of 10 // initialized ints
Dynamic Arrays • Using the new keyword causes the allocation to occur • When we’re done with an array created dynamically, we need to get rid of it with the delete keyword • Otherwise it will result in a memory leak delete [] pia;
Functions • So far the only one we’ve seen is main() • Functions are defined by a name, and a set of operands • Function prototype is the return type, name and parameters int gcd(int v1, int v2) { while (v2) { int temp = v2; v2 = v1 % v2; v1 = temp; } return v1; }
Functions • In order to use a function, we use the call operator, or () // get values from standard input cout << “Enter two values: \n”; int i,j; cin >> i >> j; // call gcd on arguments i and j // and print their greatest common divisor cout << “gcd: “ << gcd(i,j) << endl;
Functions • The parameters (int v1 and int v2 for gcd) of the function are initialized when the function is called • The arguments to a function become the parameters once inside the function • Sometimes you’ll hear these used interchangeably • The type of an argument must match its coresponding parameter • Any parameters and any variables defined inside the function have local scope • they exist only inside the body of the function • Must also have a return type, which says what kind of object will come out of the function
Functions • Return types can be built-in types, class types, or compound types bool is_present(int *, int); int count(const string &, char); Date &calendar(const char*); void process(); • Can’t return a function or an array, but can return pointers to functions and arrays • You must specify a return type in Standard C++ (even if it’s void, or int)
Functions • Parameter lists must specify the type for every parameter void process() { /* … */ } // legal void process(void) { /* … */ } // legal int manip(int v1, v2){ /* … */} // illegal int manip(int v1, int v2){/* … */} // legal • Names are optional on parameters, but to use them, they must have names
Functions • Parameters are checked at compile-time to see if the argument types match gcd(“hello”, “world”); gcd(24312); gcd(42, 10, 0); • All of the above cause compile-time errors gcd(3.14, 6.29); // no error; converts doubles to ints
Functions • What’s wrong with these function definitions (if anything)? (a) int f() { string s; // … return s; } (b) f2(int i) { /* … */ } (c) int calc(int v1, int v1) { /* … */ } (d) double square(double x) return x * x;
Functions • Parameters that are not references are initialized by copying the arguments • Changes to the values inside the function will not change them outside the function void swap(int a, int b) { int c = a; a = b; b = c; return; } int main() { int x = 5, y = 4; swap(x,y); cout << “The values are: “ << x << ““ << y << endl; return 0; } The values are: 5 4
Functions • In order to change the values, we need to use pointers! void swap(int *a, int *b) { int c = *a; *a = *b; *b = c; return; } int main() { int x = 5, y = 4; swap(&x,&y); cout << “The values are: “ << x << ““ << y << endl; return 0; } The values are: 4 5
Functions • Or we can use references: void swap(int &a, int &b) { int c = a; a = b; b = c; return; } int main() { int x = 5, y = 4; swap(x,y); cout << “The values are: “ << x << ““ << y << endl; return 0; } The values are: 4 5
Functions • Do not return a reference to a local variable // Disaster: Function returns a reference to a local object const string &manip(const string& s) { string ret = s; // transform ret in some way return ret; // Wrong: returning a reference to a local object! }
Class Functions • Back to Sales_item class Sales_item { public: // operations on Sales_item objects double avg_price() const; boolsame_isbn(constSales_item &rhs) const { return isbn == rhs.isbn } private: std::string isbn; unsigned units_sold; double revenue; }
Class Functions • Looking at same_isbn: bool same_isbn(const Sales_item &rhs) const { return isbn == rhs.isbn } • Body is a block • isbn is private, but this is not an error – private members can be accessed by class functions