Bir faydası std::beginvestd::end dış sınıflar için standart arayüz uygulamak için uzatma noktaları olarak hizmet vermeleridir.
Kullanmak isterseniz CustomContainerile sınıf beklediği döngü veya şablon işlevi için aralık tabanlı .begin()ve .end()yöntemleri, belli ki bu yöntemleri uygulamak gerekir.
Sınıf bu yöntemleri sağlarsa, bu bir sorun değildir. Bunu yapmadığında, değiştirmeniz gerekir *.
Bu, her zaman mümkün değildir, örneğin harici kütüphane, özellikle ticari ve kapalı kaynak olan.
Böyle durumlarda std::beginve std::endkullanışlı, çünkü sınıfın kendisini değiştirmeden yineleyici API'si sağlayabilir, ancak serbest fonksiyonları aşırı yükleyebilir.
Örnek:count_if bir çift yineleyici yerine bir kapsayıcı alan bir işlevi uygulamak istediğinizi varsayalım . Böyle bir kod şöyle görünebilir:
template<typename ContainerType, typename PredicateType>
std::size_t count_if(const ContainerType& container, PredicateType&& predicate)
{
using std::begin;
using std::end;
return std::count_if(begin(container), end(container),
std::forward<PredicateType&&>(predicate));
}
Şimdi, bu gelenekle kullanmak istediğiniz herhangi bir sınıf için count_if, bu sınıfları değiştirmek yerine yalnızca iki ücretsiz işlev eklemeniz gerekir.
Şimdi, C ++, Bağımsız Değişken Bağımlı Arama adlı bir mekanizmaya sahip
(ADL) sahip ve bu yaklaşımı daha da esnek hale getiriyor.
Kısacası, ADL, bir derleyici niteliksiz bir işlevi çözdüğünde (örneğin, beginyerine ad alanı olmayan işlev std::begin), bağımsız değişkenlerinin ad alanlarında bildirilen işlevleri de dikkate alacağı anlamına gelir . Örneğin:
namesapce some_lib
{
// let's assume that CustomContainer stores elements sequentially,
// and has data() and size() methods, but not begin() and end() methods:
class CustomContainer
{
...
};
}
namespace some_lib
{
const Element* begin(const CustomContainer& c)
{
return c.data();
}
const Element* end(const CustomContainer& c)
{
return c.data() + c.size();
}
}
// somewhere else:
CustomContainer c;
std::size_t n = count_if(c, somePredicate);
Bu durumda, nitelikli adların olması önemli değildir some_lib::beginve some_lib::end
- çünkü içinde CustomContainerolduğu için some_lib::derleyici bu aşırı yükleri kullanacaktır.count_if .
Bu da sahip sebebi var using std::begin;ve using std::end;içinde count_if. Bu, kalifiye olmayan kullanmamıza izin verir beginve endbu nedenle ADL'ye
izin verir ve derleyicinin seçmesine std::beginve std::endbaşka alternatif bulunmadığına izin verir .
Biz çerez yiyip çerez olabilir - yani özel bir uygulama sağlamak için bir yol var begin/ ' endderleyici standart olanları geri düşebilir iken.
Bazı notlar:
Aynı nedenden ötürü, benzer başka işlevler de vardır: std::rbegin/ rend,
std::sizeve std::data.
Diğer cevaplardan bahsedildiği gibi, std::versiyonlar çıplak diziler için aşırı yüklenmelere sahiptir. Bu yararlıdır, ancak yukarıda tarif ettiğim şeyin özel bir örneğidir.
std::beginŞablon kodu yazarken ve arkadaşlarını kullanmak özellikle iyi bir fikirdir, çünkü bu, bu şablonları daha genel hale getirir. Şablon olmayanlar için de geçerliyse yöntemleri de kullanabilirsiniz.
PS: Bu yazının yaklaşık 7 yaşında olduğunun farkındayım. Karşıya çıktım çünkü yinelenen olarak işaretlenen ve burada hiçbir cevabın ADL'den bahsetmediğini keşfettiği bir soruyu cevaplamak istedim.