6.7.4 Fonksiyon belirleyicileri
C99 yeni bir özelliği:inline
anahtar, C uyarlanmıştır ++ a, fonksiyon belirteci sadece işlev bildirimleri kullanılabilir. Bir arama yerinde bir işlev tanımının görünmesini gerektiren program optimizasyonları için kullanışlıdır. (Standardın bu optimizasyonların yapısını belirlemeye çalışmadığını unutmayın.)
İşlevin iç bağlantısı varsa veya dış bağlantısı varsa ve çağrı, dış tanımla aynı çeviri birimindeyse görünürlük sağlanır. Bu durumlarda, inline
işlevin bir bildiriminde ya da tanımında anahtar sözcüğün mevcudiyeti,
anahtar sözcük olmadan bildirilen diğer işlevlerin çağrıları yerine bu işlevin çağrılarının optimize edilmesi gerektiği yönündeki bir tercihi belirtmenin ötesinde hiçbir etkiye sahip değildir inline
.
Görünürlük, çağrının işlevin tanımından farklı bir çeviri biriminde olduğu harici bağlantıya sahip bir işlev çağrısı için bir sorundur. Bu durumda, inline
anahtar kelime, çağrıyı içeren çeviri biriminin, işlevin yerel veya satır içi bir tanımını da içermesine izin verir.
Bir program, harici bir tanımı olan bir çeviri birimi, satır içi tanımı olan bir çeviri birimi ve bir işlev için tanımlanmamış ancak bildirimi olan bir çeviri birimi içerebilir. İkinci çeviri birimindeki çağrılar, her zamanki gibi harici tanımı kullanacaktır.
Bir fonksiyonun satır içi tanımı, harici tanımdan farklı bir tanım olarak kabul edilir. Bir func
satır içi tanımın görülebildiği bir yerde harici bağlantıya sahip bir işlev çağrısı meydana gelirse, davranış, çağrının başka bir işleve, örneğin __func
dahili bağlantıyla yapılmış olmasıyla aynıdır
. Uygun bir program hangi işlevin çağrıldığına bağlı olmamalıdır. Bu, Standart'taki satır içi modeldir.
Uygun bir program, satır içi tanımı kullanan uygulamaya veya harici tanımı kullanan uygulamaya güvenmemelidir. Bir işlevin adresi her zaman harici tanıma karşılık gelen adrestir, ancak bu adres işlevi çağırmak için kullanıldığında, satır içi tanım kullanılabilir. Bu nedenle, aşağıdaki örnek beklendiği gibi davranmayabilir.
inline const char *saddr(void)
{
static const char name[] = "saddr";
return name;
}
int compare_name(void)
{
return saddr() == saddr();
}
Uygulama, çağrılardan biri için satır içi tanımı ve diğeri saddr
için harici tanımı kullanabileceğinden, eşitlik işleminin 1 (doğru) olarak değerlendirilmesi garanti edilmez. Bu, satır içi tanım içinde tanımlanan statik nesnelerin, dış tanımdaki karşılık gelen nesnelerden farklı olduğunu gösterir. Bu, kısıtlamayı const
, bu türden olmayan bir nesneyi tanımlamaya bile motive etti .
Satır içi, Standart'a, mevcut bağlayıcı teknolojisi ile uygulanabilecek şekilde eklenmiştir ve C99 satır içi satırının bir alt kümesi C ++ ile uyumludur. Bu, bir satır içi işlevin tanımını içeren tam olarak bir çeviri biriminin işlev için harici tanım sağlayan birim olarak belirtilmesi gerekerek başarılmıştır. Bu belirtim, ya inline
anahtar sözcüğü içermeyen ya da her ikisini de içeren bir bildirimi içerdiğinden inline
ve extern
bir C ++ çevirmeni tarafından da kabul edilecektir.
C99'da satır içi yapmak, C ++ spesifikasyonunu iki şekilde genişletir. İlk olarak, bir işlev
inline
bir çeviri biriminde bildirilmişse inline
, diğer tüm çeviri birimlerinde bildirilmesine gerek yoktur . Bu, örneğin, kitaplık içinde satır içine alınacak, ancak yalnızca başka bir yerde harici bir tanımla kullanılabilen bir kitaplık işlevine izin verir. Harici işlev için bir sarmalayıcı işlevi kullanmanın alternatifi, ek bir ad gerektirir; ve bir çevirmen aslında satır içi ikame yapmazsa performansı da olumsuz etkileyebilir.
İkinci olarak, bir satır içi işlevin tüm tanımlarının "tamamen aynı" olması gerekliliği, programın davranışının bir çağrının görünür bir satır içi tanımıyla mı yoksa bir işlevi. Bu, bir satır içi tanımın belirli bir çeviri biriminde kullanımı için özelleştirilmesine izin verir. Örneğin, bir kütüphane fonksiyonunun harici tanımı, aynı kütüphanedeki diğer fonksiyonlardan yapılan çağrılar için gerekli olmayan bazı argüman doğrulamalarını içerebilir. Bu uzantılar bazı avantajlar sunar; ve uyumluluk konusunda endişe duyan programcılar daha katı C ++ kurallarına uyabilirler.
Uygulamaların standart kitaplık işlevlerinin satır içi tanımlarını standart başlıklarda sağlamasının uygun olmadığını unutmayın, çünkü bu, başlıklarını ekledikten sonra standart kitaplık işlevlerini yeniden bildiren bazı eski kodları bozabilir. inline
Anahtar kelime fonksiyonlarının inlining önermek için taşınabilir bir yol sağlamaktır olmak içindir. Standart başlıkların taşınabilir olması gerekmediğinden, uygulamalar şu satırlar boyunca başka seçeneklere sahiptir:
#define abs(x) __builtin_abs(x)
veya standart kütüphane işlevlerini satır içi yapmak için taşınabilir olmayan diğer mekanizmalar.