In this class, we delve into advanced concepts of C++ focusing on operators, expressions, and statements. We'll explore assignment operators and their right-associativity, including how they differ from comparison operators. You'll learn about the legality and implications of various assignments, including compound and increment/decrement operators. We'll also cover dereferencing pointers and utilizing the arrow operator for class objects. Engage in hands-on examples demonstrating how these concepts interlink for precise and error-free coding, making complex expressions comprehensible and manageable.
###
Une image / un lien ci-dessous est fourni (tel quel) pour télécharger la présentation
Politique de téléchargement : le contenu du site vous est fourni TEL QUEL pour votre information et votre usage personnel ; il ne peut être vendu, concédé sous licence ni partagé sur d’autres sites sans l’accord de son auteur.Le contenu vous est fourni TEL QUEL, pour votre information et votre usage personnel uniquement.Téléchargez la présentation en cliquant sur ce lien.Lors du téléchargement, si vous ne parvenez pas à télécharger une présentation, l’éditeur a peut-être supprimé le fichier de son serveur.Pendant le téléchargement, si vous ne parvenez pas à obtenir une présentation, le fichier a peut-être été supprimé par l’éditeur.
F I N
Plus de contenu associé
Transcription de la présentation
C++ crash course Class 7 more operators, expressions, statements
Agenda • More operators! • getting values from combining operands • Expressions • strings of tokens that return a value • Statements • a line of code in C++
Assignment Operators • Assignment operators • An assignment is when we put a value in a variable • Left-hand operand must be a non-constlvalue inti, j, ival; constint ci = i; // alright; initializing 1024 = ival; // bad i + j = ival; // bad ci = ival; // bad
Assignment Operators • Array names are nonmodifiable: you can use subscript and dereference, but you can’t change the array itself int ia[10]; ia[0] = 0; // OK *ia = 0; // OK ia = ???; // bad!
Assignment Operator • Result of an assignment is the left-hand operand; type is the type of the left-hand operand ival = 0; // result: type int value 0 ival = 3.14159; // result: type int value 3 What happens here? inti = 10, j = 5; i = j = 4;
Assignment Operator • Result of an assignment is the left-hand operand; type is the type of the left-hand operand ival = 0; // result: type int value 0 ival = 3.14159; // result: type int value 3 What happens here? inti = 10, j = 5; i = j = 4; // assignment is right-associative
Assignment Operators • Assignment is right-associative; other binary operators are left associative Result of the rightmost assignment is assigned going left int ival; int *pval; ival = pval = 0; // error: can’t assign the val of a pointer to an int string s1, s2; s1 = s2 = “OK”; // alright; “OK” the char * literal gets converted to a string
Assignment Operators • Assignment has low precedence (happens last) inti = get_value(); while(i != 42) { i = get_value(); } How can we do this in one line?
Assignment Operators inti; while ((i = get_value()) != 42) { // do something } Without the parentheses, what happens? while (i = get_value() != 42) { // do something weird... }
Assignment Operators • That means BE CAREFUL whether you are using the comparison operator == or the assignment operator =! if (i = 42) if (i == 42) What’s the difference?
Assignment Operators What are i and d after each assignment? int i; double d; d = i = 3.5; i = d = 3.5;
Assignment Operators • What’s the difference here? if (42 = i) // ... if (i = 42) // ...
Compound Assignment Operators += -= *= /= %= // arithmetic operators (there are also bitwise operators, but we’re not going to talk about those) a = a op b; is the same as op= But the left-hand operand gets evaluated only once – mostly this doesn’t matter, except when it does (we might see cases of this later)
Assignment Operators • This is illegal. Why? double dval; intival; int *pi; dval = ival = pi = 0;
Assignment Operators • These are legal, but they’re not going to do what you might expect them to... • What should’ve been written? • if (ptr = retrieve_pointer() != 0) • if (ival = 1024) • ival += ival + 1;
Assignment Operators • Increment and decrement ++, -- inti = 0, j; j = ++i; // prefix j = i++; // postfix Note: prefix operator does less work! (Why?)
Assignment Operators • Combining dereference and increment... vector<int>::iterator iter = ivec.begin(); while (iter != ivec.end()) cout << *iter++ << endl; // iterator postfix increment What gets printed out? Why?
Assignment Operators • *iter++ : precedence of postfix increment is higher than the dereference operator *iter++ is the same as *(iter++)
Assignment Operators • Even though it’s a little confusing, experienced C++ programmers are more likely to use this kind of expression (*iter++) • so if you see C++ code, this is probably what you’ll see!
Assignment Operators • What would change if the while loop was written like so? vector<int>::iterator iter = ivec.begin(); while(iter != ivec.end()) cout << *++iter << endl;
Arrow Operator • You’ve seen the dot operator... item1.same_isbn(item2); // run the same_isbn function of item1 anim1.same_animal(anim2); // run the same_animal function of anim1
Arrow Operator • What if instead of having an explicit Animal_type, we instead have a pointer? Animal_type *ap = &anim1; (*ap).same_animal(anim2); But you have to be careful – what does this do? *ap.same_animal(anim2);
Arrow Operator • Thus we have the arrow operator -> ap->same_animal(anim2); It’s just syntactic sugar, but makes it much easier not to make mistakes!
Arrow Operator • Let’s write code: Define a vector of pointers to strings Read the vector, printing each string and its corresponding size
Arrow Operator • Assume iter is a vector<string>::iterator • Which of the following are legal? • What do they do? • *iter++; • *iter.empty(); • ++*iter; • (*iter)++; • iter->empty(); • iter++->empty();
Conditional Operator int i = 10, j = 20, k = 30; int maxVal = i > j ? i : j; What’s maxVal after this?
Conditional Operator • It’s a useful convention, but don’t abuse it int max = i > j ? i > k ? i : k : j > k ? j : k; What does the above do?
Conditional Operator • Equivalent to this... int max = i; if (j > max) max = j; if (k > max) max = k;
Conditional Operator • Fairly low precedence • In an output expression: cout << (i < j ? i : j); // works as expected cout << (i < j) ? i : j; // prints 1 or 0 – why? cout << i < j ? i : j; // error – why?
Conditional Operator • Writing code: Prompt the user for a pair of numbers, say which is smaller
Conditional Operator • Write code Process elements in a vector<int>, replacing any value that’s odd with twice its value
sizeof Operator • Returns a value of type size_t • Size in bytes of an object or type name – how much space it’s taking up in memory sizeof (type name); sizeof (expr); sizeof expr; (Remember when I said that doing ptr++ will cause it to move forward by a certain amount in memory?)
sizeof Operator • Can be used in multiple ways... Animal_typeanim, *pa; sizeof(Animal_type); sizeofanim; sizeof *pa;
sizeof Operator • Evaluating sizeofexprdoes not evaluate the expression sizeof *p; // will work even if p is a null pointer or invalid address!
sizeof Operator • Result of sizeof depends on the type involved • sizeof char or an expression of type char is 1 • sizeof a reference type returns the size of the memory necessary to contain an object of the referenced type • sizeof a pointer returns the size needed to hold a pointer; to obtain the size of the object, the pointer must be dereferenced • sizeof an array is equivalent to taking sizeof the element type, times the number of elements in the array
sizeof Operator • We can figure out the number of elements in an array this way! • (since there’s no array.size()) How?
sizeof Operator • What’s the output of this program going to be? [[ size of an int: 4 bytes; size of an int *: 8 bytes ]] int x[10]; int *p = x; cout << sizeof(x) / sizeof(*x) << endl; cout << sizeof(p) / sizeof(*p) << endl;
Compound Expressions • An expression with two or more operators is a compound expression • Must understand how precedence and associativity work in order to evaluate expressions • Precedence doesn’t necessarily specify order of evaluation, but it does determine what the answer will be
Precedence • We saw this yesterday: • How does this get evaluated? 6 + 3 * 4 / 2 + 2; Parentheses can override precedence ((6 + ((3 * 4) / 2) + 2) vs ((6 + 3) * 4) / 2 + 2
Associativity • Specifies how to group operators at the same precedence level Assignment is right associative Arithmetic is left associative
Precedence • When you know what the precedence is, it’s okay not to parenthesize – when you’re not sure, parenthesizing can help make sure that the program does what you want it to • Helpful in debugging: getting a weird result? Add parentheses around the things you thought were getting evaluated first • You can also look up the precedence for all the operators, but unless you’re an expert C++ programmer, it’s unlikely that you’ll be able to remember all of them • Useful to know for any programming language
new and delete • Has to do with allocating memory • We talked about this with dynamic arrays • We can also use it for single objects inti; // named, unitializedint int *pi = new int; // pi points to a dynamically allocated, unnamed, uninitialized int
new and delete • We need to initialize dynamically allocated objects too, even if they’re not named int i(1024); int *pi = new int(1024); string s(10, ‘9’); string *ps = new string(10, ‘9’); Must use direct-initialization syntax, rather than copy-initialization, to initialize dynamically allocated objects
new and delete • Without an explicit initializer, a dynamically allocated object is initialized in the same way as a variable inside a function • If there’s a default constructor, uses that; if it’s built-in, it’s uninitialized After each line, which is / are initialized? string *ps = new string; int *pi = new int;
new and delete • We can also value-initialize a dynamically allocated object • Default constructor, or basic type to 0 string *ps = new string(); int *pi = new int(); cls *pc = new cls();
new and delete • So that’s new... • ...why do we have delete? • Back in the day using new too many times could easily exhaust all your memory, causing a bad_allocexception • In order not to have our memory used up, we should free it using the delete expression delete pi; This will ONLY WORK for dynamically allocated variables; for all others it’s illegal – the behavior is undefined
new and delete int i; int *pi = &i; string str = “dwarves”; double *pd = new double(33); Which of these is safe? delete str; delete pi; delete pd;
new and delete int i; int *pi = &i; string str = “dwarves”; double *pd = new double(33); Which of these is safe? delete str; delete pi; // Watch out: some compilers will accept this even though it’s illegal! delete pd;
Connexion au compte
Connectez-vous pour publier votre contenu sur SlideServe.