C ++ ve Java'da çağrı kurallarında bazı farklılıklar vardır. C ++ 'da teknik olarak sadece iki kural vardır: değere göre by-pass ve referans-by-pass, üçüncü bir by-pointer konvansiyonu (aslında bir işaretçi tipinin by-pass değeri) olan bazı literatürler. Bunun da ötesinde, semantiği artırarak argümanın türüne sabitlik ekleyebilirsiniz.
Referans ile geç
Başvuru yoluyla iletmek, işlevin kavramsal olarak nesnenin bir kopyasını değil, nesne örneğinizi alacağı anlamına gelir. Başvuru, kavramsal olarak çağıran bağlamda kullanılan nesnenin diğer adıdır ve boş olamaz. İşlev içinde gerçekleştirilen tüm işlemler, işlev dışındaki nesneye uygulanır. Bu kural Java veya C'de mevcut değildir.
Değere göre geç (ve işaretçi geçerek)
Derleyici, çağıran bağlamda nesnenin bir kopyasını oluşturur ve bu kopyayı işlevin içinde kullanır. İşlev içinde gerçekleştirilen tüm işlemler harici öğeye değil kopyaya yapılır. Bu, Java'daki ilkel türler için bir kuraldır.
Özel bir sürümü bir işaretçiye (nesnenin adresi) bir işleve geçiriyor. İşlev imleci alır ve imlecin kendisine uygulanan tüm işlemler kopyaya (imleç) uygulanır, öte yandan, kayıttan çıkarılmış imlece uygulanan işlemler o hafıza konumundaki nesne örneğine uygulanır, böylece işlev yan etkileri olabilir. Bir işaretçinin nesneye göre by-pass değerinin kullanılmasının etkisi, dahili işlevin, referans by pass ile olduğu gibi harici değerleri değiştirmesine izin verir ve isteğe bağlı değerlere de izin verir (bir boş gösterici geçirir).
Bu, bir fonksiyonun harici bir değişkeni değiştirmesi gerektiğinde C'de kullanılan kuraldır ve Java'da başvuru türleriyle kullanılır: başvuru kopyalanır, ancak başvurulan nesne aynıdır: başvuru / işaretçideki değişiklikler dışarıda görünmez işlev, ancak sivri bellekte değişiklikler vardır.
Denkleme const ekleme
C ++ 'da, farklı düzeylerde değişkenler, işaretçiler ve referanslar tanımlarken nesnelere sabitlik atayabilirsiniz. Bir değişkeni sabit olarak bildirebilir, sabit bir örneğe başvuru bildirebilir ve sabit nesnelere tüm işaretçileri, değişken nesnelere sabit işaretçileri ve sabit öğelere sabit işaretçileri tanımlayabilirsiniz. Tersine Java'da yalnızca bir sabitlik düzeyi (son anahtar kelime) tanımlayabilirsiniz: değişkenin düzeyi (ilkel türler için örnek, referans türleri için referans), ancak değişmez bir öğeye başvuru tanımlayamazsınız (sınıf kendisi değilse iletmenin).
Bu, C ++ çağrı kurallarında yaygın olarak kullanılmaktadır. Nesneler küçük olduğunda, nesneyi değere göre geçirebilirsiniz. Derleyici bir kopya oluşturur, ancak bu kopya pahalı bir işlem değildir. Diğer türler için, işlev nesneyi değiştirmezse, türün sabit bir örneğine (genellikle sabit başvuru adı verilir) bir başvuru iletebilirsiniz. Bu, nesneyi kopyalamaz, ancak işleve iletir. Ancak aynı zamanda derleyici, nesnenin işlevin içinde değiştirilmediğini garanti edecektir.
Temel kurallar
İzlenmesi gereken bazı temel kurallar şunlardır:
- İlkel türler için by-pass değerini tercih edin
- Diğer türler için sabite referanslarla referans by pass'ı tercih et
- İşlevin bağımsız değişkeni değiştirmesi gerekiyorsa, doğrudan referans kullanın
- Argüman isteğe bağlıysa, pass-by-pointer kullanın (isteğe bağlı değerin değiştirilmemesi gerekiyorsa sabitlemek için)
Bu kurallardan ilki bir nesnenin sahipliğini ele alan başka küçük sapmalar da vardır. Bir nesne dinamik olarak yeni ile ayrıldığında, delete (veya [] sürümleri) ile ayrılmalıdır. Nesnenin yok edilmesinden sorumlu olan nesne veya işlev kaynağın sahibi olarak kabul edilir. Bir kod parçasında dinamik olarak ayrılmış bir nesne oluşturulduğunda, ancak sahiplik farklı bir öğeye aktarıldığında, genellikle işaretçi anlambilimiyle veya mümkünse akıllı işaretçilerle yapılır.
Kenar notu
C ++ ve Java referansları arasındaki farkın önemi konusunda ısrar etmek önemlidir. C ++ 'da başvurular kavramsal olarak nesnenin örneğidir, ona erişimci değildir. Bunun en basit örneği bir takas işlevi uygulamaktır:
// C++
class Type; // defined somewhere before, with the appropriate operations
void swap( Type & a, Type & b ) {
Type tmp = a;
a = b;
b = tmp;
}
int main() {
Type a, b;
Type old_a = a, old_b = b;
swap( a, b );
assert( a == old_b );
assert( b == old_a );
}
Yukarıda takas fonksiyonu değişiklikleri referans yoluyla her iki bağımsız değişkenleri. Java'daki en yakın kod:
public class C {
// ...
public static void swap( C a, C b ) {
C tmp = a;
a = b;
b = tmp;
}
public static void main( String args[] ) {
C a = new C();
C b = new C();
C old_a = a;
C old_b = b;
swap( a, b );
// a and b remain unchanged a==old_a, and b==old_b
}
}
Kodun Java sürümü, başvuruların kopyalarını dahili olarak değiştirir, ancak gerçek nesneleri harici olarak değiştirmez. Java başvuruları, değere göre işlevlere geçirilen işaretçi aritmetiği olmayan C işaretçileridir.