2009-09-08 22 views
10

Bazen bir dizenin uzunluğunu bir sabitle karşılaştırmak gerekir. Örneğin
:Derleme zamanı "strlen()" etkili mi?

if (line.length() > 2) 
{ 
    // Do something... 
} 

Ama kodunda "sihirli" sabitleri kullanmaktan kaçınmak çalışıyorum.
Genellikle böyle kodu kullanın: Çünkü işlev çağrısı daha okunabilir, ancak verimli

if (line.length() > strlen("[]")) 
{ 
    // Do something... 
} 

. oldukça iyi kod üreten bir yayın oluşturma yılında

template<size_t N> 
size_t _lenof(const char (&)[N]) 
{ 
    return N - 1; 
} 

template<size_t N> 
size_t _lenof(const wchar_t (&)[N]) 
{ 
    return N - 1; 
} 

// Using: 
if (line.length() > _lenof("[]")) 
{ 
    // Do something... 
} 

(2008 VisualStudio):

cmp dword ptr [esp+27Ch],2 
jbe 011D7FA5 

Ve iyi bir şey derleyici dahil olmamasıdır
ben aşağıdaki gibi şablon işlevlerini yazdı ikili çıktıdaki "[]" dizesi.

Derleyici özel bir optimizasyon mu yoksa ortak bir davranış mı?

+2

muhtemelen tüm dizi tipleri için bir şablon kullanabilir şey bu yalan: 'template size_t _lenof (const T (&) [N]) {N dönüş - 1; } ', örneğinizle aynı şekilde çalışmalıdır. –

+2

@Evan Teran: İyi fikir, ancak bu işlevler '\ 0' sona erdirme nedeniyle yalnızca dizeler (char/wchar_t dizisi) için anlamlıdır. İşleviniz int [10] için çalışmak ve dönecektir 9 - Ben mantıklı olduğunu düşünmüyorum;) – Dmitriy

+0

@Dmitriy: gerçekten –

cevap

4

Bir işlev çağrısı satır içi özelliği, bir derleyiciye özgü en iyi duruma getirme ve ortak bir davranıştır. Yani, birçok derleyici bunu yapabilir, ancak zorunlu değildir.

+0

(sadece) inlining gerektirmez istenen optimizasyon kullanabilirsiniz) uzun süre (4 yıldır VS kullanmadım. Dize uzunluğunun derleme zamanında hesaplanmasını gerektirir. –

+0

Bu gerçekten bir optimizasyon değil. Uzunluk, çalışma zamanında hesaplanmayacak ve yine de herhangi bir '_lenof' işlevini çağırmayacaktır. Standart *, dizgi değişmezleri türüne 'const char [N] 'vermek için * uygulama gerektirmez mi? Ve derleyicinin şablon işlevinin argümanlarını 'N' olarak algılamasını sağlamak için bu tür değerler gerekli değil mi? –

+0

Maalesef, cevabınızın ne ifade ettiğini yanlış anladım - nedense “strlen] işlev çağrısından dolayı verimli değil” diye konuşuyordum. Bir derleyici _lenof satır içi, o zaman muhtemelen bir şey satır içi edemez ve genel olarak oldukça zayıf bir C++ derleyici olurdu. Şablonların ciddi bir şekilde kullanılması kabus olurdu ... –

12

Neden

 
sizeof "[]" - 1; 

(eksi sondaki null bir Sen sizeof yapabileceğini "[]" -. '\ 0' sizeof ama '\ 0' genellikle sizeof olduğunu sizeof (int) C, ve "- 1" mükemmel okunabilir olan)

+0

geniş dizeler için işe yaramaz (örneğin, L "[]"). Geniş dizeler için – Dmitriy

+1

düzeltilebilir. gibi bir şey: '(sizeof (L "[]")/sizeof (L "")) - 1' –

+0

@Evan Teran: evet, ama bunu daha okunabilir hale getirmek için makro kullanmalıdır. IMHO makroları daha fazla C stili ama C++ değil – Dmitriy

-7
#define TWO 2 
#define STRING_LENGTH 2 
/* ... etc ... */ 

Ciddi, neden sadece bir 2 yazarak önlemek için tüm bu güçlük geçiyor.? Dürüstçe kodunuzu daha az okunabilir hale getirdiğinizi düşünüyorum ve diğer programcılar, kullanılmış kahveyi süzgeçten çekiyormuşsunuz gibi bakacaklar.

+0

sadece bir örnek. Gerçek kodda "bazı dize" gibi görünüyor. Bu durumda karakter sayısını saymak mı? :) – Dmitriy

+0

Evet, öyleyim. Ve yapacağım. Ve ben yaparım. –

+2

@Jed Smith: :) Dize değiştiğinde makro tanımını değiştirmeyi unutmadığınızdan emin misiniz? – Dmitriy

2

Çoğu derleyicinin, en iyi duruma getirme etkin olduğunda en iyi duruma getireceğini düşünüyorum. Devre dışı bırakıldıysa, programınızı gerekenden daha fazla yavaşlatabilir.

Çalışma zamanında strlen numaralı telefonu aramama garantisi verildiğinden şablon işlevlerinizi tercih ederim. Tabii ki, daha doğrusu char ve wchar_t için ayrı işlevleri yazmak yerine, başka bir şablon argüman ekleyin ve her tür için çalışan bir işlev alabilir: (zaten açıklamalarda belirtildiği gibi bu komik sonuçlar verecektir

template <typename Char_t, int len> 
int static_strlen(const Char_t (&)[N] array){ 
    return len/sizeof(Char_t) - 1; 
} 

)

son bir not ints dizisi geçmesine karşın, bunu yapmak olasıdır? o dizeleri için içindir, sonuçta eğer, adı _strlenkötü olduğunu. Alt alan adıyla başlayan ad alanı kapsamındaki tüm adlar uygulamaya ayrılmıştır. Bazı kötü adlandırma çakışmaları riski var.

Bu arada, neden "[]" 2'den daha az bir sihir sabiti var?Her iki durumda da

, bu dizenin biçimi değişiklikleri ile karşılaştırıldığında ise değiştirilmelidir bir hazır olduğunu.

+0

Sebebi ne olursa olsun, işleviniz strlen kullanmaktan daha hızlı görünmüyor. Ancak, std :: char_traits :: length kullanmaktan daha hızlı görünüyor, bu yüzden strlen yalnızca char dizilerde çalışıyor olduğundan hala işe yarar. – leetNightshade

İlgili konular