C ++ 'da satır içi işlevler. Amaç ne?


19

Okuduğum şeye göre, derleyici bir satır içi işlevin işlev çağrısını gövdesiyle değiştirmek zorunda değildir, ancak bunu yapabiliyorsa yapacaktır. Bu beni düşündürdü - durum buysa neden satır içi kelimeye sahibiz? Neden tüm işlev satır içi işlevlerini varsayılan olarak yapmıyorsunuz ve derleyicinin çağrıları işlev gövdesiyle değiştirip değiştiremeyeceğini anlamasına izin vermiyor musunuz?


1
İşte . Sayfa 6
EpsilonVector

Yanıtlar:


40

inlineC, C'den; C ++ için yeni değildi.

Programcının kod optimizasyonuna yardımcı olması için tasarlanmış C anahtar sözcükleri ( registerve inline) vardır. Bunlar genellikle günümüzde yok sayılmaktadır, çünkü derleyiciler kayıt atamada daha iyi yapabilir ve fonksiyonların ne zaman satır içi yapılacağına karar verebilir (aslında bir derleyici satır içi olabilir veya farklı zamanlarda satır içi değil). Modern işlemcilerde kod üretimi, Ritchie C'yi icat ederken yaygın olan daha belirleyici olanlardan çok daha karmaşıktır.

Kelimenin şu andaki anlamı, C ++ 'da, birden fazla özdeş tanımlamaya sahip olması ve onu kullanan her çeviri biriminde tanımlanması gerektiğidir. (Başka bir deyişle, satır içine alınabildiğinden emin olmanız gerekir.) inlineÜstbilgide sorunsuz bir işleve sahip olabilirsiniz ve sınıf tanımında tanımlanan üye işlevleri otomatik olarak etkili olur inline.


3
Tarihi için +1 inline.
Tamara Wijsman

11
Ben inlinezaten C .... bir satıcı uzantısı olarak kullanılabilir olmasına rağmen, ilk C ++ standartlaştırılmış eminim Evet, C99 C standardına eklendi görünüyor.
Ben Voigt

@Ben Voigt: Haklısın. İlk olarak C.'de karşılaştım.
David Thornley

5
Ayrıca, yalnızca tarihin yanlış olmadığını, inlineC99 ve sonraki sürümlerin kurallarının inlineC ++ kurallarından farklı olduğunu unutmayın .
Alf P. Steinbach

27

Başlangıçta inline, işleve yapılan çağrıların satır içine alınması gereken çok güçlü bir ipucuydu.

Ancak, garantili tek etki, inlinebir işlevin birden çok çeviri biriminde tanımlanmasına (etkili bir şekilde aynı şekilde) izin vermektir; örneğin, tanımı bir başlık dosyasına yerleştirirsiniz.

Günümüzde, bazı derleyiciler satır içi ipucunu izlemeye çok heveslidir, örn. G ++. Ve bazı derleyiciler daha az ciddiye alırlar, örneğin Visual C ++. Ama hepsinin garantiye uyması gerekiyor.

Bu iki anlamın (optimizasyon ipucu ve bağlayıcı düzeyinde anlaşılır bir tanım olarak adlandırabileceğimiz) aynı anahtar kelimede bulunması talihsiz bir durumdur, çünkü pratikte diğeri olmadan bir tanesine sahip olamayacağınız anlamına gelir.

O, aynı zamanda talihsiz bir inline(ya da daha iyi, atılabilir tanımı konusunda, ayrı bir anahtar kelime) uygulanabilir ¹cannot veri .

Yalnızca başlık modülleri daha popüler hale geldikçe, bağlayıcı düzeyinde farkedilebilir verilere duyulan ihtiyaç artmıştır. Örneğin, çoğu Boost alt kütüphanesi yalnızca başlıklıdır.

Ancak veriler için şablonlarla biraz hile uygulayabilirsiniz. Bazı sınıf şablonlarında tanımlayın, bir typedefşablon parametresi void(veya her neyse) sağlayın . Bunun nedeni, Tek Tanımlama Kuralının şablonlar için özel bir istisna oluşturmasıdır.

Notlar:
¹ inlinedeğişkenleri C ++ 17'de desteklenecektir .


1
Hakkında ek bilgi için +1 inline.
Tamara Wijsman

1
" Etkili olarak özdeş " aslında çok zor bir durumdur, çünkü çok kötü tasarlanmış C ++ dilleri normal olarak yetkin ve dikkatli programcıların statik nesneleri kullanan makul ancak resmi olarak tanımlanmamış kod yazmalarını sağlamak için çok uğraşmaktadır - kaç komite üyesinin tuzağa düştüğünü merak ediyorum
curiousguy

6

Neden tüm fonksiyonları varsayılan olarak satır içi yapmıyorsunuz? Çünkü bu bir mühendislik ödülü. En az iki tür "optimizasyon" vardır: programı hızlandırmak ve programın boyutunu (bellek kapladığı alanı) azaltmak. Inlining genellikle işleri hızlandırır. Fonksiyon çağrısı tepesinden kurtulur, istiflenerek parametreler yığından çekilir. Bununla birlikte, aynı zamanda programın bellek ayak izini büyütür, çünkü her işlev çağrısı artık işlevin tam koduyla değiştirilmelidir. İşleri daha da karmaşık hale getirmek için, CPU'nun sık kullanılan bellek parçalarını ultra hızlı erişim için CPU'daki bir önbellekte sakladığını unutmayın. Programın bellek görüntüsünü yeterince büyük yaparsanız, programınız önbelleği verimli bir şekilde kullanamaz ve en kötü durumda satır içi program aslında programınızı yavaşlatabilir.


5
Ancak derleyici bunu genel olarak programcıdan daha iyi anlayabilir (ve yapar!). Yani bu geçerli bir argüman değil.
Konrad Rudolph

" her işlev çağrısı artık işlevin tam koduyla değiştirilmelidir " Ve satır içi işlev, çağrı sırasının atlandığı ve işlevin derleme kodunun yerine kopyalandığı bir işlev değildir. Üst düzey ara kod satır içi getirilerek bir satır içi işlev yerine derlenir. Bu, derleyicinin işlev gövdesini etkili bir şekilde temiz bir makro (temiz makro, C önişlemci makrolarının tuhaflıklarına sahip olmayan bir yöntem) olarak işlemesine olanak tanır ve potansiyel olarak birçok optimizasyon sağlar.
curiousguy

3

“Satır içi” anlamak için tarihi ve 20 (ve 30) yıl önce yaşamın nasıl olduğunu anlamanız gerekir .

Belleği az olan bilgisayarlara kod yazıyorduk, bu yüzden bir derleyicinin bir seferde bir program oluşturan tüm kodu işlemesi mümkün değildi. Derleyici de çok yavaştı, bu yüzden değişmemiş kodu yeniden derlemek zorunda kalmadınız - tüm projeleri yeniden derlemek için 24 saatten fazla (bir üst arabadan daha pahalı bir bilgisayarda) alarak birkaç proje için normaldi üzerinde çalıştı.

Bu nedenle, her kod dosyası ayrı olarak bir nesne dosyalarına derlendi. Her nesne dosyası, içerdiği tüm işlevin listesiyle birlikte işlevin “adresi” ile başladı. Bir nesne dosyası ayrıca çağrının konumu ile birlikte diğer nesne dosyalarında çağırdığı tüm işlevlerin bir listesine sahipti.

Bir bağlayıcı öncelikle nesne dosyalarını okumak ve onlar içinde bulundukları dosya ve orada adresiyle birlikte, ihraç tüm fonksiyonların bir listesini oluşturmak istiyorum. Daha sonra, tüm “harici” işlev çağrılarını işlevin adresiyle güncellerken tüm nesne dosyalarını yeniden program dosyasına gönderir.

Bağlayıcı, derleyici tarafından üretilen makine kodunu harici işlev çağrılarına yapılan referansları düzeltmekten başka bir şekilde değiştirmedi veya optimize etmedi. Bağlayıcı işletim sisteminin bir parçasıydı ve çoğu derleyiciden önce geliyor. İnsanlar yeni bir derleyici yazdıklarında, geçerli bağlayıcılarla çalışmak ve geçerli nesne dosyalarına bağlanmak için ona ihtiyaç duyuyorlardı, aksi takdirde sistem çağrıları yapılamadı.

Derleyici, kodun yalnızca dahil edilen tüm başlık dosyalarıyla birlikte derlediği “.c” veya “.cpp” dosyasında görüldü. Bu nedenle, diğer “.c” veya “.cpp” dosyalarındaki koda dayalı bir optimizasyon yapamadı.

“Satır içi” anahtar sözcüğü, bir işlev (yöntem) gövdesinin bir başlık dosyasında tanımlanmasına izin verdi, böylece derleyicinin onu çağıran kodu derlerken işlevin kodunu kullanmasına izin verdi. Örneğin, anter .cpp dosyasında tanımlı bir koleksiyon sınıfınız olduğunu, bu sınıfın bir kod satırı içeren bir "isEmpty" yöntemine sahip olacağını, bir işleve çağrı yapmak yerine, sonuçta ortaya çıkan programda büyük bir hızlanma olacağını varsayalım , işlev çağrısı bu tek satırla değiştirildi.

"Satıriçi" anahtar kelimesi, o zaman çok sayıda programcının nesnenin özel alanlarına erişmesine gerek olmadan, işlev çağrılarının maliyetinden kaçınırken verilerin kapsüllenmesine izin vermenin "ucuz ve kolay" bir yolu olarak görülüyordu. (Çok daha kötü bir yolun “satır içi” kodunun, o zamanlar yaygın olanları kodladığı makrolar.)

Bu günlerde “bağlayıcılar” çok sayıda kod optimizasyonu yapıyor ve bazı ekip tarafından derleyici olarak yazılma eğiliminde. Derleyici genellikle kodun doğru olup olmadığını kontrol eder ve kodunu "sıkıştırarak" makine kodu oluşturma görevinin çoğunu bağlayıcıya bırakır.


2

Standardın ne dediğine bakalım (önemli kısımları kalın harflerle vurgulanmıştır):

2. Satır içi belirleyicili işlev bildirimi satır içi işlevi bildirir. Satır içi belirteç, uygulamaya , çağrı noktasındaki fonksiyon gövdesinin satır içi ikamesinin , alışılmış fonksiyon çağrısı mekanizmasına tercih edileceğini belirtir . Çağrı sırasında bu satır içi yerine koymayı gerçekleştirmek için bir uygulama gerekli değildir ; ancak, bu satır içi ikame atlanmış olsa bile, satır içi işlevler için diğer kurallara da uyulmalıdır.

- C ++ standardı, ISO / IEC 14882: 2003 , 7.1.2 Fonksiyon Spesifikasyonları [dcl.fct.spec]

Bu nedenle, emin olmak istiyorsanız, derleyicinizin belgelerini okumalısınız.

Her şeyi satır içine almak kötü bir fikirdir, çünkü birçok çoğaltılmış makine kodu ile sonuçlanabilir ...

Yani bilmeniz gerekenler:

Basit bir cevap yok: En iyi olanı görmek için onunla oynamak zorundasınız. Do not "Hiçbir zaman kullanımı gibi basit cevaplar razı inlinefonksiyonlar" veya "Her zaman kullanım inlinefonksiyonları" veya "Kullanım inlineişlevi daha az kod N satırlarından daha ancak ve ancak fonksiyonları." Bu tek bedene uyan kuralların yazılması kolay olabilir, ancak optimal olmayan sonuçlar üretirler.

- C ++ SSS, Satır İçi İşlevler , 9.3 İşlevlerinline performansı artırır mı?


1
Söyledikleriniz doğru, ancak ilgili değil çünkü programcı olarak satır içi veya satır içi karar vermek değil. Anahtar kelimeyi koyarsanız, işlevlerinizi satır içine alabilir veya getirmeyebilirsiniz. Anahtar kelimeyi koymazsınız, yine de onları satır içine alabilir veya girmeyebilirsiniz. Anahtar kelimeyi koyduğunuzda HERHANGİ BİR kurala sahip olmanız anlamsızdır, derleyicinin gerçekten kararını veren şeydir.
Kate Gregory

Seninle tamamen aynı diyorsa, bu nasıl alakalı değil? Basit bir cevap yok .
Tamara Wijsman

Alakalı soruya cevap vermediği için ilgili değil. “Satır içi ne yapar” sorusunu sormuyor, “ne demek istediğini” soruyor. Ve cevabınız, satır içi hakkında zaten bildiklerimizi tekrarlıyor.
Davor Ždralo

@Davor: "Amaç ne?" SSS'ye uymuyor, bu yüzden soru içinde sorulan soruları cevaplıyorum. Ben inlineOP'yi bir parçayı kaçırmış gibi göründüğü için bilgiyi tekrarlayarak söylüyorum, bu yüzden onu anlamamasının temel nedeni budur. Birinin bir noktaya gelmesi için o noktanın altında ne olduğunu anlaması gerekiyor ...
Tamara Wijsman

Neden SSS'ye uymuyor? Standart, satır içi anahtar kelimenin sözdizimini ve anlambilimini açıklar ve OP'nin sorusu, amaç nedir, ne zaman kullanılmalı, hangi sorunları çözmesi gerekiyor? Bunun SSS'ye nasıl uymadığını görmüyorum.
Davor Ždralo

1

Satır içi anahtar kelimeyi kullanmanız için size iyi bir neden vereyim.

Bilet yazıcısı veya benzeri daha küçük bir sistem gibi yerleşik bir sistemde. İşlemci çok sınırlıdır ve bir fonksiyon çağrısı (yığın, çağrı, yığınlardan param getirme ve cevaplama vb. Gibi fonksiyon parametrelerini hazırlama), fonksiyonun kendisinin yanında birkaç ms sürebilir.

Diyelim ki çağrı süresi yaklaşık 60 ms (sadece işlev için değil, gerçek işlev için) ve 50 yineleme (bir ağaçta döngü veya yinelemeli çağrılar) yapıyorsunuz.

Bu işlev çağrısından ileri geri hareket süresi 60 * 50 = 3000 (3 saniye) sürecektir.

Eğer hafızanız varsa, kesinlikle 3 saniye kazanmak için satır içi yapmalısınız.

Yani inline temel olarak yürütme hızına ihtiyacınız olduğunda kullanılır. Katıldığım bazı projelerde, çağrı süresi yürütme süresinden daha uzundu, satır içi kullanıldığında klasik bir durum.


Ne? Kodunuza satır içi koymanız, derleyicinin satır içi satılacağı anlamına gelmez ve orada koymamak da alışkanlık anlamına gelmez. Bu sadece bugünün derleyicileri tarafından göz ardı edilen bir ipucu. Derleyici satır içi yapmayı yararlı bulursa, aksi takdirde olmayacaktır. Orada gerçek bir kontrolünüz yok. OP bunu zaten biliyor ve şu soruyu soruyor: "Amaç nedir?" Kim bu konuda +1 verir? Hem yanıltıcı (satır içi anahtar kelimenin satır içi zorlamayı zorunlu kıldığı anlamına gelir) hem de soru ile alakasız.
Davor Ždralo

2
@Davor Ždralo Kaba olmanıza gerek yok. Soruyu neden satır içi kullanmalıyım olarak yorumladım? Demek istediğim, kodu bellekte daha hızlı alabileceğinizi göstermekti. Her derleyici satır içi anahtar sözcüğü farklı işleyebilir, bu yüzden bahsetmediğim belgeleri kontrol etmeniz gerekir. Ekstra bellek ek yükü satırlarının oluşturduğu her zaman göze alamayacağınız için, ne zaman kullanılacağını "yönlendirmek" yararlıdır. Ayrıca satır içi çizgilerin zorlandığını söylemedim. Birisi bu cevabı kendisi için yararlı buldu ve +1 oy verdi, lütfen diğerinin başka bir deneyim seviyesine sahip olabileceğine ve önemsiz bir şey bulabileceğine saygı gösterin.
Max Kielland
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.