Yanıtlar:
Ben tercih ediyorum it - vec.begin()
Naveen'in verdiği zıt bir nedenle kesin: bu kadar olmaz bir liste haline vektör değiştirirseniz derlemek. Bunu her yineleme sırasında yaparsanız, bir O (n) algoritmasını O (n ^ 2) algoritmasına çevirebilirsiniz.
Başka bir seçenek, yineleme sırasında kapsayıcıda atlamazsanız, dizini ikinci bir döngü sayacı olarak tutmak olacaktır.
Not: it
bir kapsayıcı yineleyicinin ortak adıdır std::container_type::iterator it;
.
it
?
std::container_type::iterator it;
std::list
, öğelere konumlarına göre doğrudan erişim sunmadığından, yapamazsanız list[5]
, yapamamanız gerekir list.begin() + 5
.
std::distance(vec.begin(), it)
Herhangi bir kod değişikliği olmadan kap değiştirmek için izin verecek gibi tercih ederim . Örneğin, rasgele erişim yineleyicisi sağlama std::list
yerine kullanmaya karar verirseniz std::vector
, kodunuz yine de derlenir. Std :: distance, yineleyici özelliklerine bağlı olarak en uygun yöntemi aldığından, performansta herhangi bir düşüş olmaz.
vec
kötü bir haber var. Kod genel olarak yeniden yazıldıysa, kapsayıcı türünü şablon parametresi olarak alarak, o zaman rasgele erişimli yineleyicilerin ele alınması hakkında konuşabiliriz (ve yapmalıyız) ;-)
vec
kötü bir haber.
UncleBens ve Naveen'in de gösterdiği gibi, her ikisi için de iyi nedenler var. Hangisi "daha iyi" ne istediğinize bağlıdır: Sabit zamanlı davranışı garanti etmek istiyor musunuz, yoksa gerektiğinde doğrusal zamana geri düşmesini istiyor musunuz?
it - vec.begin()
sabit zaman alır, ancak operator -
yalnızca rastgele erişim yineleyicilerde tanımlanır, bu nedenle kod örneğin liste yineleyicilerle hiç derlenmez.
std::distance(vec.begin(), it)
tüm yineleyici türleri için çalışır, ancak yalnızca rasgele erişim yineleyicilerde kullanılırsa sabit zamanlı bir işlem olur.
Hiçbiri "daha iyi" değildir. İhtiyacınız olanı kullanın.
Bunu beğendim: it - vec.begin()
çünkü bana açıkça "başlangıçtan itibaren mesafe" diyor. Yineleyiciler ile aritmetik olarak düşünmeye alışkınız, bu yüzden -
burdaki burç en açık göstergedir.
distance
mı?
it++
böyle bir şey söylemiyoruz std::increment(it)
, öyle değil mi? Bu daha az net sayılmaz mı?
++
Operatör biz yineleyici artırmak olarak nasıl STL dizilerinin bir parçası olarak tanımlanır. std::distance
ilk ve son eleman arasındaki eleman sayısını hesaplar. Aslında -
operatör çalışır sadece bir tesadüftür.
Algoritmanızı bir std::vector::iterator
ve std::vector::iterator
sadece kullanmakla kısıtlanmış / sabit kodlanmışsanız, hangi yöntemi kullanacağınız önemli değildir. Algoritmanız, diğerinden birini seçmenin herhangi bir fark yaratabileceği noktanın ötesinde somutlaştırılmıştır. İkisi de aynı şeyi yapıyor. Bu sadece kişisel bir tercih meselesidir. Şahsen açık bir çıkarma kullanırdım.
Öte yandan, gelecekte bir günün başka bir yineleyici türüne uygulanabilmesine izin vermek için algoritmanızda daha yüksek bir genelliği korumak istiyorsanız, o zaman en iyi yöntem niyetinize bağlıdır . Burada kullanılabilecek yineleyici türüyle ilgili olarak ne kadar kısıtlayıcı olmak istediğinize bağlıdır.
Açık çıkarma kullanırsanız, algoritmanız oldukça dar bir yineleyici sınıfıyla sınırlandırılır: rasgele erişimli yineleyiciler. (Bu şimdi aldığınız şeydir std::vector
)
Kullanırsanız distance
, algoritmanız çok daha geniş bir yineleyici sınıfını destekler: giriş yineleyicileri.
Tabii ki, distance
rasgele erişimli olmayan yineleyiciler için hesaplama genel olarak verimsiz bir işlemdir (yine, rasgele erişimli olanlar için çıkarma kadar etkilidir). Algoritmanın rasgele erişimli yineleyiciler için verimlilik açısından anlamlı olup olmadığına karar vermek size kalmıştır . Ortaya çıkan verimlilik kaybı, algoritmanızı tamamen işe yaramaz hale getirme noktasına yıkıcıdır, o zaman çıkarmaya daha iyi yapışmanız, böylece verimsiz kullanımları yasaklamanız ve kullanıcıyı diğer yineleyici türleri için alternatif çözümler aramaya zorlamanız gerekir. Rasgele erişimli yineleyicilerle verimlilik hala kullanılabilir aralıktaysa, distance
algoritmanın rasgele erişimli yineleyicilerle daha iyi çalıştığı gerçeğini kullanmalı ve belgelemelisiniz.
Göre http://www.cplusplus.com/reference/std/iterator/distance/ , çünkü vec.begin()
a, rasgele erişim yineleyici, mesafe yöntemi kullanan -
operatör.
Yani cevap, performans açısından aynıdır, ancak distance()
kodunuzu okumak ve anlamak zorunda olup olmadığını anlamak daha kolaydır.
-
Varyantı std::vector
sadece için kullanırım - ne anlama geldiği oldukça açıktır ve operasyonun basitliği (bir işaretçi çıkarma işleminden daha fazla değildir) sözdizimi ile ifade edilir ( distance
diğer tarafta, pisagor gibi sesler) ilk okuma, değil mi?). UncleBen'in belirttiği -
gibi vector
, kazayla değiştirildiği takdirde statik bir iddia olarak da hareket eder list
.
Ayrıca bence çok daha yaygın - bunu kanıtlayacak sayı yok. Ana argüman: it - vec.begin()
kaynak kodunda daha kısadır - daha az yazma işi, daha az yer kaplama. Sorunuza verilen doğru yanıtın bir zevk meselesi olduğu anlaşılmaktadır, bu da geçerli bir argüman olabilir.
İşte indeks ile birlikte 10'un "all" oluşumlarını bulmak için bir örnek. Bunun biraz yardımcı olacağını düşündüm.
void _find_all_test()
{
vector<int> ints;
int val;
while(cin >> val) ints.push_back(val);
vector<int>::iterator it;
it = ints.begin();
int count = ints.size();
do
{
it = find(it,ints.end(), 10);//assuming 10 as search element
cout << *it << " found at index " << count -(ints.end() - it) << endl;
}while(++it != ints.end());
}