Bir Java referansının bir C işaretçisinden farkı nedir?


97

C işaretçilere sahip ve Java referans denilen şeye sahiptir. Hepsinin bir şeye işaret ettiği anlamında ortak bazı noktaları vardır. C işaretçilerinin işaret ettikleri adresleri sakladığını biliyorum. Referans ayrıca adresi saklıyor mu? Bu işaretçinin daha esnek ve hataya eğilimli olması dışında nasıl farklılar?


10
Not C ++ 'da işaretçilerden veya java referanslarından farklı referanslar vardır
jk.

@jk. Java ile aynı olacağını düşündüm. Farkı nedir?
Gnijuohz

17
C ++ referansları yeniden fiyatlandırılamaz (yani, belirlenen nesneyi değiştiremezsiniz) ve dikkate alınamaz (yani geçerli olarak hiçbir nesneye referans veremezsiniz).
AProgrammer

@Gnijuohz @ AProgrammer'ın söylediklerini tekrarlama: Java'daki bir finalreferans, neredeyse bir C ++ referansına eşittir. Tam olarak eşdeğer olmamalarının nedeni , bir C ++ referansının ayrıca ek olarak geçersiz olmamasıdır, oysa finalJava'daki bir referans geçersizdir .
Utku,

Yanıtlar:


142

Adresler saklanarak referanslar uygulanabilir. Genellikle Java referansları imleç olarak uygulanır, ancak şartname gerektirmez. Çöplerin daha kolay toplanabilmesi için ek bir indirme katmanı kullanıyor olabilirler. Fakat sonunda (neredeyse her zaman) (Java tarzı) referansların uygulanmasında yer alan (C tarzı) işaretçilere kaybolacak.

İşaretçilerle aritmetik işlemleri referanslarla yapamazsınız. C'deki bir işaretçi ile Java'daki bir referans arasındaki en önemli fark, Java'daki bir referansın temel değerini gerçekten alamamanız (ve değiştirememeniz). Başka bir deyişle: işaretçi aritmetik yapamazsınız.

C'de bir işaretçiye (yani adres) bir şey ekleyebilir veya "yakındaki" şeyleri veya herhangi bir yerdeki yerleri gösterecek bir şeyi çıkarabilirsiniz .

Java'da referans bir şeye ve sadece o şeye işaret eder. Bir değişkeni farklı bir referansta tutabilirsiniz , ancak sadece "orijinal şeyden sonraki şeyi" göstermesini isteyemezsiniz.

Referanslar kesinlikle yazılmıştır. Bir başka fark, bir referans türü olmasıdır kadar bir olabilir bir işaretçi türü C olarak C'de bir daha daha sıkı Java kontrollü int*ve onu at char*ve sadece bu konumdaki hafızayı yeniden yorumlamak. Yani yeniden yorumlanması Java çalışmaz: Eğer sadece bir şey olarak referans diğer ucundaki nesneyi yorumlayabilir zaten (bir yayınlayabileceğim yani Objectbaşvurusunu Stringbaşvuru yalnızca nesne işaret etmek aslında bir olduğunu String).

Bu farklılıklar C işaretçilerini daha güçlü, aynı zamanda daha tehlikeli hale getirir. Bu olasılıkların her ikisi de (işaretçi aritmetik ve işaret edilen değerlerin yeniden yorumlanması) C'ye esneklik katar ve dilin gücünün bir kısmının kaynağıdır. Ancak bunlar aynı zamanda büyük sorun kaynaklarıdır, çünkü yanlış kullanılırsa, kodunuzun etrafta oluşturulduğu varsayımlarını kolayca çözebilirler. Ve onları yanlış kullanmak oldukça kolaydır.


18
İçin 1 gücüyle . Uygulama detaylarına güvenmeyin.
Mart'ta CVn

2
+1 Çöp toplama özelliği, belirli bir kalın nokta olarak belirtilmeyi hak etmiyor mu? Bu, C işaretçilerin daha güçlü, ancak aynı zamanda daha tehlikeli olmalarıdır (işaretçilerin hafızanın bozulmasına neden olan
boş

Referanslar ve işaretçiler arasındaki diğer bir fark, C'deki bir göstergenin bir sayı dizisine dönüştürülmesidir (örneğin, bir a'ya memcpygeçmek için kullanılır char[]) ve bunun tersi de geçerlidir. Bir işaretçi, bir yerde depolanan bir sayı dizisine dönüştürülürse (ekranda gösterilebilir ve operatör tarafından bir kağıt kağıdına kopyalanabilir), bilgisayardaki işaretçinin tüm kopyaları imha edilir ve bu sayı dizisi dönüştürülür. imlece geri dönün (belki de operatör tarafından girildikten sonra), imleç yine de aynı şeyi göstermelidir. Bir program ...
supercat

... bir işaretçiyi sayılar olarak görüntüler ve ardından el ile girilen sayıları bir göstergeye dönüştürür, "kötülük" olabilir, ancak geçerli bir form oluşturduğu gösterilmeyen sayılarla yazılmadığı sürece Tanımsız Davranışları çağırmaz Işaretçi. Bu nedenle, genel amaçlı çöp toplama tamamen taşınabilir C'de imkansızdır, çünkü bilgisayarın bir işaretçinin kopyasının evrende bir yerinde olup olmadığını bilmesi mümkün değildir.
supercat,

JLS, §4.3.1'e göre, Java'daki referanslar işaretçilerdir, bu yüzden "Genellikle Java referansları işaretçiler olarak uygulanır, ancak şartname için bu gerekli değildir." yanlış.
Lew Bloch

8

C ++ referansları yine farklı.

İlklendirilmeleri gerekir ve boş olamazlar (en azından iyi oluşturulmuş bir programda değil) ve başka bir şeye atıfta bulunmak için tekrar edilemezler. Bir C ++ başvurusu, bir nesnenin diğer adı gibidir.

İşaretçiler ve Java / C ++ referansları arasındaki diğer önemli bir fark, bir referansın adresine erişemediğiniz bir işaretçinin adresini alabilmenizdir (aslında bir C ++ referansının aslında bellekte bir nesne olarak bulunmasına gerek yoktur); işaretçi için işaretçi, ancak başvuru referansı değil


4

Java Referansları ve C işaretçileri tam olarak iki noktada farklılık gösterir:

  1. Birincisi için işaretçi-aritmetik yoktur.
  2. Ve ne istersen bir Java referansı oluşturamazsın, sadece erişilebilir bir yere (statik alanlar, nesnelerin alanları, yerel değişkenler) kaydedilmiş olanları veya fonksiyon çağrıları tarafından döndürülenleri (yapıcı-çağrılar gibi) kopyalayabilirsin, bu yüzden hepsi Java ile ilgilidir. nesneler (asla referanslar gibi temel türlere char, intvb.).

Birisi Kaynakça'nın çok yazıldığını yazdı, çünkü derleyiciyi bir int*gibi davranmaya zorlayamazsınız char*.
Tamamen, belirli bir dönüşümün gerçekten güvenli olduğu gerçeğinin yanı sıra, C'de herhangi bir polimorfizm yoktur, bu nedenle karşılaştırma bir başlangıç ​​değildir.
Kuşkusuz, Java, C'den daha güçlü bir şekilde yazılmıştır, C işaretçilerinin Java referanslarına göre bir özelliği olmadığından değil, JNI'yi tür güvenliğini bozmak için kullanmanız gerekir (genel kısıtlamaları göz ardı etmeden), ancak C'de bile zorlamanız gerekir. derleyici

Birisi, Java referanslarının , JVM C'ye uygulanmışsa, genellikle olduğu gibi, 32Bit makinelerde kesinlikle daha az güçlü olduklarından emin olduğumu söylediğim C işaretçiler olarak uygulanabileceğini yazdı . 64Bit makinelerde, yerden ve bant genişliğinden tasarruf etmek için normal olarak sıkıştırılmış sıradan nesne işaretçilerdir ("sıkıştırılmış OOP").
Her neyse, bu C işaretçilerinin tipik olarak (>>>% 99) performans nedenleriyle olsa bile donanım adresleriyle eşdeğer olmaları gerekmez.
Son olarak, programlayıcıya açık olmayan bir uygulama detayı.


-1

Onlar biraz farklı. Java'da referansın bir kopyası çağrılan fonksiyonun yığınına kopyalanır, çağıran fonksiyonla aynı nesneye işaret eder ve bu nesneyi değiştirmenize izin verir. Ancak, çağrı işlevinin başvurduğu nesneyi değiştiremezsiniz.

Aşağıdaki java kodunu göz önünde bulundurun

public static void changeRValue(StringBuffer sb){
    sb = new StringBuffer("helllllo"); /*attempt to assign the reference
                                        to a new object*/
}
public static void main(String[] args) {
    StringBuffer sb = new StringBuffer("hi");     //Create a new string buffer
    changeRValue(sb);                             //Call changeRValue
    System.out.println(sb.toString());            //Prints "hi" not "hello"
}

Şimdi bir c ++ işaretçisi düşünün:

void func(Dog* dog){
    *dog = Dog("hello world"); //Change the value of dog to a new object
}

int main(int argc, const char * argv[]) {
    Dog dog1("hi");                            //Create a dog object
    func(&dog1);                               //pass the address of dog
    cout << dog1.name;                         //Prints "hello world" not hi.
    return 0;
}

Bunun bir
kötüye

2
Java'daki sivri uçlu nesneyi C ++ ile aynı şekilde değiştirebilirsiniz. Sadece doğru üyelere erişiminiz olmalı. Java nesneleri atama operatörlerine sahip değildir, çünkü Java kullanıcı tanımlı operatör aşırı yüklemesini desteklemez, bu yüzden aşırı yüklenmiş bir operatör kullanamazsınız, çok fazla şey. Java eksikliğinin, Java referanslarının, pointer aritmetiğinden bağımsız olarak C ++ işaretçileriyle aynı olması gerçeğiyle hiçbir ilgisi yoktur.
Deduplicator
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.