210 likes | 230 Views
STL Iterators. Separating Container from Data Access. Last Tutorial. C++ Templates Function templates (swap, minimum, QuickSort ) Class templates (pair) The Standard Template Library (STL) Containers Library – specifically std ::vector. Today’s Questions. What is an iterator?
E N D
STL Iterators Separating Container from Data Access
Last Tutorial • C++ Templates • Function templates (swap, minimum, QuickSort) • Class templates (pair) • The Standard Template Library (STL) • Containers Library – specifically std::vector
Today’s Questions • What is an iterator? • What operations can I perform on an iterator? • What is an std::list? • How is an std::list different from an std::vector?
What is an iterator? • An iterator identifies an element in a container • Similar to a pointer • An iterator allows us to access an element in a container • Also similar to a pointer • An iterator allows us to move between elements in a container • Similar to pointer arithmetic • An iterator is restricted to efficient operations http://en.cppreference.com/w/cpp/concept/Iterator
Iterator versus operator[] • Why not just use array[index] to access elements? • operator[] implies random access • Random access is not supported by all data structures • In the STL, all containers have iterators defined • Each of these iterator types are different: • std::vector<int>::iterator • std::vector<float>::iterator • std::list<int>::iterator
std::vector functions Already Covered Today’s New Functions Iterating – begin() Returns an iterator to the first element Iterating – end() Returns an iterator to the element following the last element Used for bounds checking • Accessing – operator[] • Inserting – push_back() • Modifying – operator[] • Querying – size() • Complexity of all of the above: • O(1) http://en.cppreference.com/w/cpp/container/vector
Where is begin and end? my_vector.size() = n Note: one past the end! … 1 2 3 4 5 n - 1 0 my_vector.begin() my_vector.end()
Operating on iterators std::vector<int> numbers ={1,2,3,4}; // Case 1 std::vector<int>::iterator it =numbers.begin(); it =5;// Case 2 it++;// Case 3 it--;// Case 4 intx =*it;// Case 5 it !=numbers.end();// Case 6 it <numbers.end();// Case 7 *it =27;// Case 8 it =numbers.begin()+2;// Case 9 iterator_operations.cpp
Looping Through a Vector std::vector<int> numbers ={1,2,3,4}; // using indices for(size_ti=0;i<numbers.size();++i){ std::cout<< numbers[i]<<" "; } std::cout<<"\n"; // using iterators for(std::vector<int>::iterator it =numbers.begin(); it !=numbers.end();++it){ std::cout<<*it <<" "; } std::cout<<"\n"; Declare iterator type Initialize to first element Ensure iterator valid Advance to next element Dereference to get value of the element vector_looping.cpp
Extract the Negative Values of the Vector std::vector<int>extract_negatives(std::vector<int>& integers){ std::vector<int> negatives; for(std::vector<int>::iterator it =integers.begin(); it !=integers.end();++it){ if(*it <0){ negatives.push_back(*it); } } return negatives; } Using iterators, loop over the integers vector and add elements that are negative to the negatives vector. extract_negatives.cpp
Erase the Negative Values of the Vector voidremove_negatives(std::vector<int>& integers){ for(std::vector<int>::iterator it =integers.begin(); it !=integers.end();){ if(*it <0){ it =integers.erase(it); }else{ it++; } } } Do not increment it in the for loop statement erase(iterator) will return an iterator to the next element it is incremented if nothing is erased remove_negatives.cpp
What does erase do? *it processed elements unprocessed elements negative elements copied it2 = integers.erase(it); processed elements unprocessed elements *it2
How does erase perform? • erase(iterator) • Accepts an iterator to the element that should be erased • Returns the next iterator in the vector • Complexity: O(n) • What is the complexity of remove_negatives? • Consider a vector that contains all negative values
How does erase perform? • erase(iterator) • Accepts an iterator to the element that should be erased • Returns the next iterator in the vector • Complexity: O(n) • What is the complexity of remove_negatives? • Consider a vector that contains all negative values • We loop over n elements • Worst case: we erase n times • Complexity: O(n2)
std::list is a Doubly Linked List next next next next • Double links (next and previous) allow for bi-directional access • Fast insert and erase • Only need to update neighbours data data data data … head tail previous previous previous previous http://en.cppreference.com/w/cpp/container/list
Iterator Categories *it it++ it-- it + 5 *it it++ it-- *it it++ http://en.cppreference.com/w/cpp/concept/Iterator
Replacing std::vector with std::list voidremove_negatives(std::list<int>&integers){ for(std::list<int>::iterator it =integers.begin(); it !=integers.end();){ if(*it <0){ it =integers.erase(it); }else{ it++; } } } voidremove_negatives(std::vector<int>&integers){ for(std::vector<int>::iterator it =integers.begin(); it !=integers.end();){ if(*it <0){ it =integers.erase(it); }else{ it++; } } } vector_vs_list.cpp
Replacing std::vector with std::list • Because of iterators, we can quickly switch from vector to list • This is one reason why iterators are so useful • With std::list, remove_negativesis O(n) • Be careful: not all code works interchangeably with all containers vector_vs_list.cpp
Using C++11’s auto keyword • Instead of specifying a type (such as int), we can use the auto keyword • auto asks the compiler to determine the type for us • Using auto can help… • Save on typing • Keep code compiling when you switch types around frequently • Caution: You should always know what the actual type will be • The type is still static • auto does not mean the type can change dynamically – this is not python http://en.cppreference.com/w/cpp/language/auto
Simplifying Iterator Code with auto // Before C++11 for(std::vector<int>::iterator it =numbers.begin(); it !=numbers.end();++it){ std::cout<<*it <<" "; } std::cout<<"\n"; // With C++11 for(autoit =numbers.begin(); it !=numbers.end();++it){ std::cout<<*it <<" "; } std::cout<<"\n"; auto_iterators.cpp