23 Kasım 2014 Pazar

STL Iterator'leri

Giriş
Iterator'ler her veri yapısında bulunuyorlar. Java ve C# gibi dillerden farklı olarak iterator'lerin çeşitleri var. Aşağıda konu ile ilgili notlarım bulunuyor.

Not : Konuyla ilgili olarak STL Stream Iteratorleri başlıklı yazıya da göz atabilirsiniz.

Iteratörler 
iterator ve end()
end() ile elde edilen nokta veriyapısının en son elemanından bir sonraki bir şeydir.Dolayısıyla her veriyapısı [begin,end) şeklinde yarı açık bir aralık verir. Aşağıdaki şekilde durum görülebilir.

Benzer bir şekil ise aşağıda.

Dolayısıyla end() ile verilen iterator'ü bir kere daha artırmaya çalışmak tanımsız davranıştır.

Bu yarı açık aralık yüzünden aşağıdaki döngü çalışır.
for (auto it = v.begin(); it != v.end(); ++it)
iterator ve erase
Bir çok STL veri yapısı için (özellikle vector için) yapıyı dolaşırken silme işlemi aşağıdaki gibi olur.
for (it = begin(); it != end(); ) {
    if (...) it = index.erase(it);
    else ++it;
}
List'te aynı şekilde çalışır. Örnek:


list<A*> myList;
list<A*>::iterator it = myList.begin();
while( it != myList.end() ) {
    (*it)->DoSomething();
    if( (*it)->WorksFnished() ) {
        it = myList.erase(it);
    } else {
        ++it;
    }
}
Burada if koşulundan sonra iterator'ün erase metodunun döndürdüğü değere eşitlendiğine dikkat etmek lazım.
erase metodu silinen elemandan bir sonraki elemanı gösteren değeri döndürür. iterator bu yeni değere eşitlendiği için ++ ile ilerletilmesi gerekmez. 

Iterator Tanımlama
İki çeşit iterator tanımlama yöntemi mevcut. İlk yöntemde iterator sınıfı veri yapısı sınıfına friend olarak tanıtılıyor. Böylece iterator veriyapısının rahatça dolaşabiliyor. STL iteratorleri bu yöntemi kullanıyorlar.Örnek:
class MyClass
{
    friend class MyClassIterator;
 private:
    Node* m_PrivateData;
}
Diğer yöntemde ise Iterator veriyapısına kendini geçerek, kullanacağı index'i veriyapısının güncellemesini istiyor.

Burada her veri yapısının Iterable arayüzünden türediği farz ediliyor. Iterable arayüzü AdvanceIterator(), GetCurrentValue() gibi arayüzler sunuyor.

Template kullanılamayan projelerde, Nesneye Yönelimli bir tasarım yapmak için bu yöntem kullanılabilir.Örnek:
bool Iterator::MoveNext()
{
    return m_pIterable->AdvanceIterator(this);
}
void* Iterator::CurrentItemValue()
{
    return m_pIterable->GetCurrentValue(this);
}
InputIterator
InputIterator yazısına taşıdım.

OutputIterator
OutputIterator yazısına taşıdım.

Random Access Iterator
Random Access Iterator sınıfı diğer iteratör sınıflarına göre en fazla özelliği sunan sınıftır. 
Vector gibi sınıfların döndürdüğü iteratorler random acces iterator olarak sınıflandırılıyor.Bu tür iteratörler "<" , "<=", ">", ">=" gibi karşılaştırmaları desteklerler. Örnek:
for(vector<int>::iterator it = myvector.begin(); it < myvector.end(); it++){
    // some code
}
Reverse Iterator
Reverse Iterator alt tarafata, ileriye doğru çalışan bir iterator'ü kullanarak çalışır. Bu yüzden base()diye bir metodu vardır.
base
Bu metod ile dikkat edilmesi gereken nokta, bir reverse iterator'de *it ve it farklı yerleri işaret ederler. Şekilde görülebilir.

Örnek:
  
  

Türetilen Iterator Fikirleri
Bir çok kütüphane kendi iterator uzantılarını sunuyor. Burada bazı iterator fikirleri var. 
Arka arkaya aynı değer varsa sadece birini dönen deduplication iterator.

Iterator Traits
iterator_traits yazısına taşıdım.

Hiç yorum yok:

Yorum Gönder