C++ Templates L03 - Iterator 10 – Iterator.

Slides:



Advertisements
Similar presentations
14 Templates. OBJECTIVES In this chapter you will learn:  To use function templates to conveniently create a group of related (overloaded) functions.
Advertisements

Templates and the STL.
STL Standard Template Library ● Good reference book: – The C++ Standard Library ● A Tutorial and Reference ● by Nicolai M. Josuttis ● 1999 – Addison Wesley.
CSE 332: C++ templates This Week C++ Templates –Another form of polymorphism (interface based) –Let you plug different types into reusable code Assigned.
More about Java Classes Writing your own Java Classes More about constructors and creating objects.
Prof. amr Goneid, AUC1 CSCE 110 PROGRAMMING FUNDAMENTALS WITH C++ Prof. Amr Goneid AUC Part 15. Dictionaries (1): A Key Table Class.
CSE 332: C++ template examples Today: Using Class and Function Templates Two examples –Function template for printing different types –Class template for.
CSE 332: C++ pointers, arrays, and references Overview of Pointers and References Often need to refer to another object –Without making a copy of the object.
CSIS 123A Lecture 7 Static variables, destructors, & namespaces.
Motivation for Generic Programming in C++
“Generic Programming” ECE 297
C ++ MULTIPLE CHOICE QUESTION
Pointers and Dynamic Arrays
Andy Wang Object Oriented Programming in C++ COP 3330
Programming with ANSI C ++
Overview 4 major memory segments Key differences from Java stack
CS 215 Final Review Ismail abumuhfouz Fall 2014.
C++ Templates.
Lecture 7-2 : STL Iterators
Motivation and Overview
C++ in 90 minutes.
Pointers and Pointer-Based Strings
C++ History C++ was designed at AT&T Bell Labs by Bjarne Stroustrup in the early 80's Based on the ‘C’ programming language C++ language standardised in.
Friday, January 26, 2018 Announcements… For Today… For Next Time…
Generic Programming Techniques in C++
Monday, March 19, 2018 Announcements… For Today… For Next Time…
Tuesday, February 20, 2018 Announcements… For Today… 4+ For Next Time…
Templates in C++.
The C++ Algorithm Libraries
Friday, February 16, 2018 Announcements… For Today… 4.5-, pgs. 252
1.4 Abstract Data Types, Interfaces, and Pre- and Postconditions
Prof. Michael Neary Lecture 7: The STL Prof. Michael Neary
Introduction to Linked Lists
Andy Wang Object Oriented Programming in C++ COP 3330
18 – Sequential Containers
C++ Templates L03 - Iterator 10 – Iterator.
10 – Iterators C++ Templates 4.6 The Iterator pgs
2.5 Reasoning about Programs: Assertions and Loop Invariants
Lecture 7-2 : STL Iterators
ADT Implementations: Templates and Standard Containers
Lab 04 – Linked List.
Object Oriented Programming COP3330 / CGS5409
C++ Functions, Classes, and Templates
3.3 Abstract Classes, Assignment, and Casting in a Hierarchy
Overview 4 major memory segments Key differences from Java stack
Lab 03 - Iterator.
15 – Sequential Containers
14 – Sequential Containers
CMSC 202 Lesson 22 Templates I.
Andy Wang Object Oriented Programming in C++ COP 3330
Abstraction: Generic Programming, pt. 2
Lecture 8-2 : STL Iterators and Algorithms
Parasol Lab, Texas A&M University
C++ Templates L03 - Iterator 10 – Iterator.
Pointers and Pointer-Based Strings
COP 3330 Object-oriented Programming in C++
Arrays Arrays A few types Structures of related data items
Templates I CMSC 202.
Java Programming Language
Lab4 problems More about templates Some STL
EE 312 Final Exam Review.
Standard Template Library
Lesson 25 Miscellaneous Topics
C++ Templates CSE 333 Winter 2019
Templates CMSC 202, Version 4/02.
14 – Sequential Containers
四時讀書樂 (春) ~ 翁森 山光照檻水繞廊,舞雩歸詠春風香。 好鳥枝頭亦朋友,落花水面皆文章。 蹉跎莫遣韶光老,人生唯有讀書好。
15 – Sequential Containers
Lab 04 - Iterator.
C++ Templates L04 - Iterator 10 – Iterator.
Presentation transcript:

C++ Templates L03 - Iterator 10 – Iterator

Attendance Quiz #11 Iterators

Tip #12: new vs. malloc Differences between malloc and new: Iterators Differences between malloc and new: Calling Constructors: new calls constructors, malloc() does not. In fact primitive data types (char, int, float.. etc) can also be initialized with new. Operator vs function: new is an operator, malloc() is a function. Return type: new is type safe and returns exact data type, malloc() returns void *. Failure Condition: On failure, malloc() returns NULL, new Throws. Memory: In case of new, memory is allocated from free store where as in malloc() memory allocation is done from heap. Overriding: We are allowed to override new operator where as we can not override the malloc() function legally. Size: Required size of memory is calculated by compiler for new, where as we have to manually calculate size for malloc(). The short answer is: Fundamentally, malloc is a C feature and new is a C++ feature. Don't use malloc with C++ without a really good reason for doing so.

Strings Are Really Templates C++ Templates Strings Are Really Templates

Template Classes and Functions Iterators C++ templates use "Instantiation-style polymorphism". A template is literally a template; a class template is not a class, it's a recipe for creating a class using template parameters. Class and function functionality can be adapted to more than one type or class without repeating the entire code for each type. template <typename T> class MyPair { private: T values [2]; public: MyPair (T first, T second) values[0]=first; values[1]=second; } }; MyPair<int> myInts(115, 36); MyPair<double> myFloats(3.0, 2.18); template <typename int> int GetMax(int a, int b) { return (a > b ? a : b); } int x,y; GetMax<int>(x, y); template <typename myType> myType GetMax(myType a, myType b) { return (a > b ? a : b); } T is the template parameter name instead of myType because it is shorter and in fact is a very common template parameter name. But you can use any identifier you like.

Iterators Nested Classes

Nested Class Iterators A nested (inner) class is a class which is declared inside an enclosing (outer) class. While an inner class is a member of the outer class and has the same access rights as any other outer class member, An inner class does not have an implicit reference to an instance of the outer class. If the inner class needs access to outer class members, you must pass an outer class reference (pointer) to the inner class, then the inner class can reference anything in the outer class instance. class Outer { class Inner Outer* ptr; Inner(Outer* p) : ptr(p) {} };

Nested Class Iterators You make the parent-child relationship manually thru a reference/pointer or constructor arguments. class Outer { private: int var; public: Outer() : var(0) {} class Inner Outer* optr; Inner(Outer* op) : optr(op) {} void add(int x) { optr->var += x; } }; Inner newInner() { return Outer::Inner(this); } int getVar() { return var; } int main() { Outer outer; Outer::Inner inner = outer.newInner(); inner.add(20); cout << outer.getVar(); return 0; } 20

Nested Class Nested classes increase encapsulation. Iterators Nested classes increase encapsulation. Nested classes can lead to more readable and maintainable code – useful for developing object models in your component. Iterators are generally implemented as nested classes. class MyClass { class Iterator }; Iterator begin() { return MyClass::Iterator(this); } Iterator end() { return MyClass::Iterator(this); }

Iterators Iterators

Array Container Access Iterators By Index #include <iostream> using namespace std; int main() { int dog[] = { 1, 2, 3, 4 }; int* dptr = dog; for (size_t i = 0; i < 4; ++i) cout << *dptr++ << endl; } return 0; By Pointer #include <iostream> using namespace std; int main() { int dog[] = { 1, 2, 3, 4 }; for (size_t i = 0; i < 4; ++i) cout << dog[i] << endl; } return 0;

 Other Containers #include <iostream> #include <vector> Iterators #include <iostream> #include <vector> using namespace std; int main() { vector<int> numbers; numbers.push_back(1); numbers.push_back(2); numbers.push_back(3); numbers.push_back(4); for (size_t i = 0; i < numbers.size(); ++i) cout << numbers[i] << endl; } return 0; #include <iostream> #include <list> using namespace std; int main() { list<int> numbers; numbers.push_back(1); numbers.push_back(2); numbers.push_back(3); numbers.push_back(4); for (size_t i = 0; i < numbers.size(); ++i) cout << numbers[i] << endl; } return 0; 

Other Containers w/Iterator Iterators #include <iostream> #include <vector> using namespace std; int main() { vector<int> numbers; numbers.push_back(1); numbers.push_back(2); numbers.push_back(3); numbers.push_back(4); vector<int>::iterator iter = numbers.begin(); while (iter != numbers.end()) cout << *iter++ << endl; } return 0; #include <iostream> #include <list> using namespace std; int main() { list<int> numbers; numbers.push_back(1); numbers.push_back(2); numbers.push_back(3); numbers.push_back(4); list<int>::iterator iter = numbers.begin(); while (iter != numbers.end()) cout << *iter++ << endl; } return 0;

Why Use an Iterator? Those who avoid using iterators: Assume your container has index ([]), at, and increment (++,--) operators. Assume your container elements can be randomly accessed, are contiguous, and same size (only true for vectors...) Have to write their own versions of common algorithms (ie., sort or reverse) Iterators bring you closer to container independence. You're not making assumptions about random-access ability, storage format, efficiency of operations such as size(), or most algorithms. You only need to know that the container has iterator capabilities. Iterators enhance your code further with standard algorithms. Depending on what it is you're trying to achieve, you may elect to use for_each(), find(), replace(), partition(), search(), transform(), sort(), … By using a standard algorithm rather than an explicit loop you're avoiding re-inventing the wheel. Your code is likely to be more efficient (given the right algorithm is chosen), correct, and reusable.

The STL Iterator Approach Iterators #include <iostream> #include "myArray" 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 <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.

Lab 03 - Iterator

You may freely use the code in any way you deem useful. ****Disclaimer**** The following code examples are flawed and incomplete, but demonstrate how an iterator class might be implemented. You may freely use the code in any way you deem useful.

Step 1 – int Array Class Iterators #include <iostream> #include <string> #include <sstream> #define MAX_ARRAY_SIZE 1000 using namespace std; class MyArray { private: size_t size_; int* array_; public: MyArray(size_t maxSize) : size_(0) { array_ = (int*)malloc(maxSize * sizeof(int)); } void push_back(int item) { array_[size_++] = item; } }; int main(int argc, char * argv[]) { MyArray numbers(MAX_ARRAY_SIZE); numbers.push_back(1); numbers.push_back(2); numbers.push_back(3); numbers.push_back(4); cout << numbers << endl; return 0; } Be sure to use a destructor to free array! string toString() const { stringstream out; out << "myArray"; for (size_t i = 0; i < size_; ++i) out << ((i % 10) ? " " : "\n") << array_[i]; return out.str(); } friend std::ostream& operator<< (ostream& os, const MyArray<T>& myArray) os << myArray.toString(); return os; Remember, every class needs a toString and a Friend!

Step 2 – Template Class Iterators #include <iostream> #include <string> #include <sstream> #define MAX_ARRAY_SIZE 1000 using namespace std; template<typename T> class MyArray { private: size_t size_; T* array_; public: MyArray(size_t maxSize) : size_(0) { array_ = (T*)malloc(maxSize * sizeof(T)); } void push_back(T item) { array_[size_++] = item; } }; int main(int argc, char * argv[]) { MyArray<int> numbers(MAX_ARRAY_SIZE); numbers.push_back(1); numbers.push_back(2); numbers.push_back(3); numbers.push_back(4); cout << numbers << endl; return 0; } Templates are a feature of the C++ programming language that allows functions and classes to operate with generic types, allowing a function or class to work on many different data types without being rewritten for each one. There are three kinds of templates: function templates, class templates and, since C++14, variable templates.

Step 3 – Add a Nested Iterator Iterators #include <iostream> #include <string> #include <sstream> #define MAX_ARRAY_SIZE 1000 using namespace std; template<typename T> class MyArray { private: size_t size_; T* array_; public: MyArray(size_t maxSize) : size_(0) { array_ = (T*)malloc(maxSize * sizeof(T)); } void push_back(T item) { array_[size_++] = item; } class Iterator size_t index_; MyArray<T>* array_ptr_; Iterator(MyArray<T>* a, size_t s) : array_ptr_(a), index_(s) { } T operator[](size_t i) const { return array_ptr_->array_[i]; } }; Iterator begin() { return MyArray<T>::Iterator(this, 0); } Iterator end() { return MyArray<T>::Iterator(this, size_); } int main(int argc, char * argv[]) { MyArray<int> numbers(MAX_ARRAY_SIZE); numbers.push_back(1); numbers.push_back(2); numbers.push_back(3); numbers.push_back(4); MyArray<int>::Iterator iter = numbers.begin(); for (size_t i = 0; i < 4; ++i) cout << iter[i] << ' '; cout << endl << endl; return 0; } MyArray Iterator Nested classes can access all members of the parent via a reference/pointer.

Step 4 – Add Functionality Iterators #include <iostream> #include <string> #include <sstream> #define MAX_ARRAY_SIZE 1000 using namespace std; template<typename T> class MyArray { private: size_t size_; T* array_; public: MyArray(size_t maxSize) : size_(0) { array_ = (T*)malloc(maxSize * sizeof(T)); } void push_back(T item) { array_[size_++] = item; } class Iterator size_t index_; MyArray<T>* array_ptr_; Iterator(MyArray<T>* a, size_t s) : array_ptr_(a), index_(s) { } bool operator!=(Iterator rhs) const { ... } T& operator*() const { ... } Iterator& operator++() { ... } }; Iterator begin() { return MyArray<T>::Iterator(this, 0); } Iterator end() { return MyArray<T>::Iterator(this, size_); } int main(int argc, char * argv[]) { MyArray<int> numbers(MAX_ARRAY_SIZE); numbers.push_back(1); numbers.push_back(2); numbers.push_back(3); numbers.push_back(4); MyArray<int>::Iterator iter = numbers.begin(); while (iter != numbers.end()) cout << *iter << ‘ ‘; ++iter; } cout << endl << endl; return 0; Add not equal (!=), dereference (*), and pre-increment (++) operators.

Output of Iterator Lab myArray: 1 2 3 4 5 6 7 8 9 10 Iterators myArray: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ITERATORS: begin(): size=20 index=0 end(): size=20 index=20 SEQUENTIAL: PRIME: 2 3 5 7 11 13 17 19 COMPOSITE: 4 6 8 9 10 12 14 15 16 18 20 FIBONACCI: 3 = 1 + 2