Presentation is loading. Please wait.

Presentation is loading. Please wait.

C++ Templates L03 - Iterator 10 – Iterator.

Similar presentations


Presentation on theme: "C++ Templates L03 - Iterator 10 – Iterator."— Presentation transcript:

1 C++ Templates L03 - Iterator 10 – Iterator

2 Attendance Quiz #12 Iterators

3 Tip #13: '\n' Confusion Program Correctness Internally all applications use '\n' to indicate line termination. But the line termination sequence is platform specific. Windows (DOS) uses CR and LF. Unix (Linux) uses LF. Mac (OSX) CR. 2 additional formats: Unicode Line Separator (LS) and Unicode Paragraph Separator (PS).

4 Tip #13: Newline Confusion
Iterators The problem with platform specific line termination is The '\n' character is transformed into a platform specific sequence of character(s) when you write it to a file. The platform specific sequence is converted back to '\n' when the file is read. The problem becomes a problem when you write files on one platform and read them on another. For example, after running "filename >> amount;", the newline is still in the buffer. This normally isn't a problem when using only ">>" as it ignores newlines. But when you mix getline and ">>" you need to ignore the newlines that ">>" leaves behind. Bad getline(cin, line, '\n'); cout << "hello\n"; filename >> amount; getline(filename, line); Good getline(cin, line); cout << "hello" << endl; filename >> amount >> std::ws;

5 Iterators typedef

6 typedef Iterators typedef is a C/C++ keyword used to create an alias name for another data type. typedef is helpful for giving a short, unambiguous alias to a portable data structure or a complicated function pointer type: typedef unsigned int size_t; typedef vector<int> MyObj; typedef MyObj::iterator Iterator; MyObj numbers; Iterator iter = numbers.begin(); Typedefs provide a level of abstraction away from the actual types being used, allowing you to focus more on the concept of just what a variable should mean. This makes it easier to write clean code, as well as make it far easier to modify your code.

7 typedef vs Using With C++11, you can use using to create a type alias.
Iterators With C++11, you can use using to create a type alias. The identifier following the using keyword becomes a typedef- name. using has the same semantics as if it were introduced by the typedef specifier. For example: typedef vector<string>::iterator StringVectorIterator; using StringVectorIterator = vector<string>::iterator; is equivalent to: In general, if you're using a C++11 compiler, you should consider using the 'using' syntax instead of typedefs.

8 Prefix / Postfix Unary Operators
Iterators Prefix / Postfix Unary Operators

9 Overload Prefix Operator
Iterators The prefix and postfix versions of the unary increment and decrement operators can all be overloaded. To allow both unary prefix and postfix increment usage, each overloaded operator function must have a distinct signature (so that the compiler can determine which version of "++" is intended.) When the compiler sees the pre-increment expression on a Data data type: Data myData; ++myData; the compiler generates the member function call: myData.operator++() The prototype for this operator function would be: Data& operator++();

10 Overload Postfix Operator
Iterators Overloading the postfix increment operator presents a challenge because the compiler must be able to distinguish between the signatures of the overloaded prefix and postfix increment operator functions. The convention that has been adopted in C++ is that when the compiler sees the post-incrementing expression object++, it generates the member function call: myData.operator++(0) The prototype for this operator function would be: Data operator++(int); The argument 0 is strictly a "dummy value" that enables the compiler to distinguish between the prefix and postfix increment operator functions.

11 Overload Postfix Operator
Iterators Postfix operators are expressions that yield the original value and then modify the object. Operator overloads are functions and thus all side effects must take place before the function completes. The only way of attaining the required semantics is by copying the initial state of the object before applying the change. The original state must be returned by value (if a reference was returned, the evaluation of the expression would yield the state of the object after the function completes, and thus would have the semantics of prefix operators, not postfix ones). A typical implementation of postfix involves Creating a temporary object local to the function, Incrementing the originally passed object using the prefix operator, And then returning the temporary object by value, not by reference since the local object is guaranteed to be alive only within the scope of the function and any access to it beyond this scope will result in Undefined Behavior.

12 Prefix and Postfix Operators
Iterators // prefix (return by reference) MyClass& operator++() { // implement increment logic, return reference to it. return *this; } // postfix (return by value) MyClass operator++(int) // the dummy int disambiguates { MyClass tmp(*this); operator++(); // prefix-increment this instance ++*this; // prefix-increment this instance return tmp; // return value before increment } **Note that this means the return value of the overloaded postfix operator must be a non-reference, because we can’t return a reference to a local variable that will be destroyed when the function exits. **Also note that this means the postfix operators are typically less efficient than the prefix operators because of the added overhead of instantiating a temporary variable and returning by value instead of reference.

13 Doggy Example… Prefix incrementer Postfix incrementer Output?
Iterators #include <iostream> using namespace std; class Dog { private: int value; public: Dog() : value(0) {} Dog& operator++() { ++value; return *this; } Dog operator++(int) { Dog temp(*this); ++value; return temp; } friend ostream& operator<<(ostream& os, Dog& d) { return os << d.value; } }; int main() Dog dog; cout << dog++ << endl; cout << ++dog << endl; return 0; } Prefix incrementer Postfix incrementer Output?

14 Lab 03 - Iterator

15 Iterator Lab Iterators The concept of an iterator is fundamental to understanding the C++ Standard Template Library (STL). Iterators provide access to data stored in container classes (e.g. vector, map, list, etc.) Your Iterator lab implements a C++ array container class that uses an iterator to access the array elements. Your container supplies begin() and end() functions. Your iterator object overloads the not equal ("!="), dereference ("*"), and pre-increment ("++") operators. Use an iterator to sequentially access elements of the associated array class. Read integer values from a file into the array class. Instantiate an iterator using the begin() function and then use the iterator to iterate thru the array values until the iterator equals the iterator returned by the end() function.

16 Lab 03 Iterator iter "points" to first element in myArray.
Iterators #include <iostream> #include "MyArray.h" using namespace std; int main() { MyArray<int> myArray; myArray.push_back(1); myArray.push_back(2); myArray.push_back(3); myArray.push_back(4); MyArray<int>::iterator iter = myArray.begin(); while (iter != myArray.end()) cout << *iter << " "; ++iter; } return 0; #include <iostream> #include <list> using namespace std; int main() { list<int> myArray; myArray.push_back(1); myArray.push_back(2); myArray.push_back(3); myArray.push_back(4); list<int>::iterator iter = myArray.begin(); while (iter != myArray.end()) cout << *iter << " "; ++iter; } return 0; #include <iostream> #include <vector> using namespace std; int main() { vector<int> myArray; myArray.push_back(1); myArray.push_back(2); myArray.push_back(3); myArray.push_back(4); vector<int>::iterator iter = myArray.begin(); while (iter != myArray.end()) cout << *iter << " "; ++iter; } return 0; iter "points" to first element in myArray. myArray.end() "points" to something NOT in myArray. Dereference iter to access myArray elements.

17 Pre-increment operator
Nested Iterator Class Iterators template<typename T> class MyArray { private: // MyArray data public: MyArray(const size_t maxSize) { ... } void push_back(T item) { ... } std::string toString() const { ... } friend ostream& operator<< (ostream& os, const MyArray<T>& myArray) { ... } }; Iterator is nested in MyArray and CAN NOT be instantiated outside of MyArray MyArray Iterator Not-equal operator class Iterator { private: // Iterator data and private functions public: Iterator(MyArray<T>* array, size_t index) { ... } bool operator!=(const Iterator& other) const { ... } // not-equal Iterator& operator++() { ... } // pre-increment ++ T& operator*() const { ... } // dereference string toString() const { ... } friend ostream& operator<< (ostream& os, const Iterator& iter) { ... } }; Iterator begin() { ... } // pointer to first element Iterator end() { ... } // pointer AFTER last element Pre-increment operator Dereference operator

18 main Open I/O Streams Read / push_back integer into numbers container.
Iterators int main(int argc, char * argv[]) { VS_MEM_CHECK ifstream in(argv[1]); std::ostream& out = (argc < 3) ? std::cout : *(new std::ofstream(argv[2]); out << endl << endl; MyArray<int> numbers(MAX_ARRAY_SIZE); int i; while (in >> i) numbers.push_back(i); out << numbers << endl << endl; out << "SEQUENTIAL" << endl; MyArray<int>::Iterator iter = numbers.begin(); out << "iter: " << iter << endl; for (; iter != numbers.end(); ++iter) out << *iter << " "; return 0; } Open I/O Streams Read / push_back integer into numbers container. Instantiate Iterator Use friend insertion operator to examine Iterator Output number's contents using dereferencing operator Loop until iter and numbers.end() are equal

19 Output of Iterator Lab myArray: 1 2 3 4 5 6 7 8 9 10
Iterators myArray: Output myArray contents using MyArray friend << operator. ITERATORS: begin(): size=20 index=0 end(): size=20 index=20 Output iterators using Iterator friend << operator. SEQUENTIAL: Output myArray contents using a MyArray iterator. PRIME: (BONUS) Output all prime numbers in myArray using a MyArray iterator. COMPOSITE: 18 20 (BONUS) Output all composite numbers in myArray using a MyArray iterator. FIBONACCI: 3 = 1 + 2 (BONUS) Output all numbers in myArray equal to the sum of the two previous numbers using a MyArray iterator.

20


Download ppt "C++ Templates L03 - Iterator 10 – Iterator."

Similar presentations


Ads by Google