2010-10-22 16 views
12

Örnek kodda sık sık çıkış yineleyicileri için *it++ gibi kodları görüyorum. *it++ ifadesi, it'un bir kopyasını it artırır ve ardından son olarak kaldırılan kopyayı döndürür. Anladığım kadarıyla, bir çıkış yineleyicisinin bir kopyasını yapmak kaynağı geçersiz kılar. Fakat daha sonra, kopya oluşturulduktan sonra yapılan it'un artırılması yasa dışı olur, değil mi? Çıkış yineleyicileriyle ilgili anlayışım hatalı mı?Çıkış iticileri için * it ++ nasıl kullanılır?

+0

Neden geçersiz bir yineleyici kopyalama (çıkış veya başka şekilde) ki? Biz böyle şeyler deyince rutin olarak yapmayın: 'vektör :: yineleyici (container.begin()); –

+0

@Adrian: Örneğin, [SGI belgeleri] (http: //www.sgi. com/tech/stl/OutputIterator.html) diyor ki: "Herhangi bir anda tek bir Çıkış Yineleyici'nin yalnızca bir etkin kopyası olmalıdır. Yani: Bir Çıkış Yineleyici'nin bir kopyasını x oluşturduktan ve kullandıktan sonra, orijinal çıktı yineleyicisi Artık kullanılmamalıdır. ” Yine de, bu bağlamda bir çıktı yineleyicisinin ne demek olduğunu tam olarak bilmiyorum. Dereferencing? Arttırım? – fredoverflow

+2

"out_iterator" a (b); ',' b 'ifadesinin, dediğiniz gibi SGI belgelerinde geçerli olmayabileceğini, ancak C++ 03'teki hiçbir şeyin ona işaret etmediğini ima ediyorum. Ancak hem SGI sayfası hem de C++ 03 açıkça ifade ederse '* it ++ = value' ifadesi geçerli olmalıdır, bu gereksinim bu kullanımla ilgili diğer endişeleri geçersiz kılar. – aschepler

cevap

6

ifade *it++, değil bir kopyasını yapmak (gerekir) does her zamanki anlamsallıktadır gibi değil artışı o vb Bu ifade yalnızca kolaylık için geçerlidir yapar. Asıl iş sadece operator= yapar. Örneğin, ostream_iterator, operator*, operator++ ve operator++(int)'un g ++ uygulamasında, sadece bir şey: return *this (başka bir deyişle, hiçbir şey!).Biz örneğin yazabilirsiniz:

it = 1; 
it = 2; 
*it = 3; 
++it = 4; 

yerine: *it++ = 1; *it++ = 2; *it++ = 3; *it++ = 4;

+1

Bu bana bir anı veren cevaptır, dolayısıyla doğru olanı seçiyorum. – fredoverflow

+0

Muhtemelen, ilk örneğin yalnızca çalıştığını ve ikinci örneğin bir çıktı yineleyicisi kullanmanın doğru yolu olduğunu bildiğinizden emin olmalısınız. – Dingo

+0

@Dingo: Eğer standardı doğru bir şekilde anlarsam, uygulamaya bağlı değil, 'ostream_iterator' için iyi tanımlanmış. Bu yüzden genel durumda, '* ++' 'bir kopyasını vb. Gerektirmez. – rafak

-4

Yineleyici sadece bir işaretçi değil mi? Artırma, sonra dereferencing sadece bir sonraki öğeye geçer.

+1

Hayır, yineleyiciler sadece işaretçi değildir. –

+0

Bir işaretçi gibi, bir işaretçi gibi, bu size kafa karışıklığı olabilir, ama hayır, onlar sadece işaretçiler değil, başka şeylerin yanı sıra, bir öğeye bir işaretçi tutarlar. İşte bir yineleyicinin örnek bir uygulaması: http://www.accu-usa.org/Listings/2000-04-Listing01.html –

+0

Ah, anlıyorum. Yinelemede noktayı hiç görmedim ve onlara hiç ihtiyacım olmadı. –

1

Çıkış yineleyicileri, normal yineleyiciler gibi çalışmazlar ve arabirimleri, kullanışlı sonuçlarla işaretçi benzeri ifadelerde (*it++ = x) kullanılabilmeleri için belirtilir.

Tipik olarak operator*(), operator++() ve operator++(int) her bir referans olarak *this döndürür ve çıktı yinelemeler beklenen çıkış işlemi gerçekleştiren bir sihirli operator= sahiptir. Bir çıktı yineleyiciden okuyamayacağınız için, operator*() vb. Diğer yineleyiciler için çalışmadığı gibi bir önemi yoktur.

14

Standart, *r++ = t çıkış yineleyicileri için çalışmasını gerektirir (24.1.2). Çalışmıyorsa, standardın tanımına göre bir çıkış yineleyici değildir.

Bu tür ifadelerin başlık altında doğru şekilde çalıştığından emin olmak için yineleyici uygulamasına kalmıştır.

Bir çıktı yineleyicisinin birden çok kopyasını saklamamanızın nedeni, tek geçişli anlambilimine sahip olmasıdır. Yineleyici sadece her bir değerde bir kez silinebilir (yani, her bir hata işlemi arasında artırılmalıdır). Bir yineleyiciden vazgeçildiğinde, bunun bir kopyası olamaz.

Bu nedenle *r++ = t çalışır. Orijinal yineleyiciden bir kopyasını alır, orijinal yineleyici kaldırılır ve kopya artırılır. Orijinal yineleyici bir daha asla kullanılmayacak ve kopya artık aynı değere referans vermiyor.

+0

Bunu mu demek istediniz t = * r ++? –

+0

@Seth No. Orijinal soru belirtilen çıkış yineleyicileri. – Dingo

+1

@Seth: Hayır, '* r ++ = t' bir çıkış yineleyicisi nasıl kullandığınızdır. Başka bir şekilde, derlemek bile gerekli değildir. – aschepler

1

Yorumunuza baktığımızda, bu karışıklığın çoğunun SGI dokümantasyonundan kaynaklandığı görülüyor, ki bu noktada biraz yanıltıcı olduğunu söyleyebilirim.

Bir çıktı yineleyici kopyalandığında, kopyalanan yineleyici geçersiz kılınır geçersiz olur. Gerçek sınırlama oldukça basittir: sadece belirli bir çıkış iteratörü değerini bir kez çıkarmalısınız. Bununla birlikte, her seferinde iki kopyasına sahip olmak, aynı değere sahipken, sadece bir kez ondan vazgeçtiğiniz sürece iyidir. Birini kaldırmayı düşündüğünüz bir durumda, sonra değerini atar ve diğerini artırır, ancak artıştan sonra bunu iptal etmek, tamamen mükemmeldir.

İlgili konular