Bir değişkeni başlatmak ne kadar önemlidir?


9

Değişkenleri başlatmak ne kadar önemlidir?

Doğru başlatma, bellek sızıntılarını önler mi veya performans avantajlarına sahip mi?


14
Dile bağlıdır. Bazı dillerde hataları önlemek oldukça önemlidir, geri kalanında okunabilirliğe yardımcı olmak için sadece iyi bir şey.
Telastyn

Girişiniz için Telastyn teşekkürler. Dile bağlı olarak önemli hale geldiği bir dava koyabilir misiniz?
Vivek

4
C ++ burada kötü şöhretli olanıdır. Hata ayıklamada, yerel değişkenler nullortak derleyiciler tarafından 0 (veya ) olarak başlatılır , ancak serbest bırakılması için derlenirken rasgele çöptür. (C ++ bilgim ~ 10 yıl öncesine ait olsa da, işler değişmiş olabilir)
Telastyn

Bir kez yakılmış-iki kez utangaç bir durum. Başlatılmamış değişkenlerin, özellikle işaretçilerin neden olduğu hataları gördüğüm / yaşadığım için, bu bir alışkanlık haline geldi. Performans için genellikle önemsizdir. Bellek sızıntıları için, gerçekten bir sorun değil.
Mike Dunlavey

1
@Telastyn bundan daha kötü. Tanımsız davranış sadece çöp durumuyla sınırlı değildir, her şey olabilir. Derleyici, başlatılmamış değişkenleri okuyan yolların erişilemez olduğunu varsayabilir ve yol boyunca oluşan "ilişkisiz" efektleri ortadan kaldırabilir.
Caleth

Yanıtlar:


7

Başlatılmamış değişkenler bir programı belirleyicisiz hale getirir. Program her çalıştığında farklı davranabilir. Çalışma ortamındaki, günün saatindeki, ayın evresindeki ve bunun permütasyonlarındaki ilgisiz değişiklikler, bu cinlerin nasıl ve ne zaman ortaya çıkacağını etkiler. Program, kusur sunulmadan önce milyonlarca kez çalışabilir, her seferinde yapabilir veya bir milyon daha çalıştırabilir. Birçok sorun "aksaklıklara" konur ve göz ardı edilir veya "Tekrar Üretilemez" olarak kapatılan müşterilerden gelen hata raporları. Bir sorunu 'düzeltmek' için ne sıklıkta makineyi yeniden başlattınız? Ne sıklıkta bir müşteriye "Bunu asla görmediniz, tekrar görürseniz bana bildirin" dediniz - tam olarak ummayacaklarını (bilerek)!

Bir hatanın yeniden üretimi test ortamında imkansızın yanında olabileceğinden, bulunması ve düzeltilmesi imkansızdır.

Genellikle kodun güvenilir ve kararlı olduğu düşünülen hatanın ortaya çıkması yıllar alabilir. Kusurun daha yeni bir kodda olduğu varsayılır - aşağı doğru izlenmesi çok daha uzun sürebilir. Derleyicideki bir değişiklik, derleyici anahtarı, hatta bir kod satırı ekleyerek davranışı değiştirebilir.

Değişkenleri başlatmak büyük bir performans avantajına sahiptir, çünkü sadece doğru çalışan bir program sonsuz olandan daha hızlı değildir, ancak geliştiriciler orada olmaması gereken hataları bulmak ve düzeltmek için daha az zaman harcarlar ve "gerçek" iş yapmak için daha fazla zaman harcarlar.

Değişkenleri başlatmanın diğer önemli avantajı, kodun orijinal yazarının neyi başlatacağına karar vermesidir. Bu her zaman önemsiz bir egzersiz değildir ve önemsiz olmadığında kötü bir tasarımın göstergesi olabilir.

Bellek sızıntıları farklı bir sorundur, ancak doğru başlatma sadece onları önlemeye yardımcı olmakla kalmaz, aynı zamanda onları tespit etmeye ve kaynağı bulmaya da yardımcı olabilir - yüksek dile bağımlıdır ve bu gerçekten verebileceğimden daha fazla araştırmaya değer ayrı bir soru. bu cevapta.

Düzenleme: Bazı dillerde (örn. C #), program derlenmediğinden veya yürütüldüğünde bir hata bildirildiğinden başlatılmamış değişkenleri kullanmak mümkün değildir. Bununla birlikte, bu özelliklere sahip birçok dilde potansiyel olarak güvenli olmayan kodun arabirimleri vardır, bu nedenle başlatılmamış değişkenleri tanıtmak için bu tür arabirimler kullanıldığında dikkatli olunmalıdır.


6
Birçok programlama dili değişkenlerini otomatik olarak önceden tanımlanmış bir değere ayarlar, burada söylediklerinizin çoğu bu diller için geçerli değildir.
Robert Harvey

2
@RobertHarvey'in söylediklerini tekrarlamak için, bunların hiçbiri C # için geçerli değildir. Değişkenlerinizi bildirirken başlatmanın hiçbir performans avantajı yoktur ve başlatılmamış bir değişken kullanmak imkansızdır, bu nedenle yeniden üretilemeyen hataları suçlayamazsınız. (O ise başlatılmamış sınıf alanını kullanmak mümkün, ama bir varsayılan değere set alır ve bu durumda bir uyarı oluşturur)
Bobson

4
@mattnz - Mesele şu ki, C # (veya Java) gibi davranan diller için, bu tavsiyelerin bazıları yanıltıcı veya düpedüz yanlıştır. Bir dil agnostik soruya gibi bu bir dil agnostik tepkisi, dilleri ele araçlara sahip olmalıdır yapmak kolu başlatıldı değişkenleri güvenle yanı sıra eşleşmeyenler.
Bobson

1
Ben de herhangi bir yarım iyi derleyici / statik analizör onlar hakkında uyarır gibi
jk

1
Java (ve muhtemelen C #) için yerel ayarları erkenden başlatmak gereksizdir ve muhtemelen daha fazla hataya yol açar. Örneğin, bir değişkeni koşullu olarak atamadan önce null olarak ayarlamak, derleyicinin koddaki yollardan birinin değişkenin atanmasına yol açmayabileceğini söyleme yeteneğini yener.
JimmyJames

7

Telastyn'in işaret ettiği gibi bir değişkenin başlatılması hataları önleyebilir. Değişken bir referans tipiyse, başlatılması satırın altındaki boş referans hatalarını önleyebilir.

Varsayılan olmayan bir değeri olan herhangi bir türdeki değişken, varsayılan değeri saklamak için biraz bellek kaplar.


6

Başlatılmamış bir değişken kullanmaya çalışmak her zaman bir hatadır, bu nedenle bu hatanın meydana gelme olasılığını en aza indirmek mantıklıdır.

Muhtemelen en yaygın yaklaşım programlama dilleri bir değişkeni başlatabilir unutma eğer öyleyse en azından, bu gibi bir şey olacak, sorun kendiliğinden ilklendir varsayılan bir değere etmektir hafifletmek amacıyla almayı 0yerine gibi bir şey 0x16615c4b.

Yine de sıfıra sıfırlanmış bir değişkene ihtiyaç duyuyorsanız, bu hataların büyük bir yüzdesini çözer. Ancak, yanlış bir değere başlatılmış bir değişken kullanmak hiç başlatılmamış bir değişkeni kullanmak kadar kötüdür. Aslında, bazen daha da kötü olabilir, çünkü hata daha ince ve algılanması zor olabilir.

Fonksiyonel programlama dilleri bu sorunu sadece başlatılmamış değerlere ve yeniden atamaya tamamen izin vermeyerek çözer. Bu sorunu ortadan kaldırır ve düşündüğünüz kadar ciddi bir kısıtlama olmadığı ortaya çıkar. İşlevsel olmayan dillerde bile, bir değişkeni başlatmak için doğru değere sahip olana kadar bildirmeyi beklerseniz, kodunuz çok daha sağlam olur.

Performansa gelince, muhtemelen ihmal edilebilir. Başlatılmamış değişkenlerle ilgili en kötü durumda, fazladan bir ödeviniz olur ve hafızayı gerekenden daha uzun süre bağlar. İyi derleyiciler birçok durumda farklılıkları optimize edebilir.

Bellek sızıntıları tamamen ilişkisizdir, ancak doğru şekilde başlatılmış değişkenler daha kısa bir süre için kapsamda olma eğilimindedir ve bu nedenle bir programcının kazara sızması olasılığı daha az olabilir.


Her zaman? "Her zaman" da olduğu gibi "Sabit bir Valgrind mesajı OpenSSL'yi işe yaramaz hale nasıl getirdi ? " Yoksa diğerini mi demek istediniz, "neredeyse her zaman" olanı?
Ocak'ta JensG

1
Başlatılmamış değişkenlere hatasız olarak izin veren üç dil düşünebilirim, bunlardan biri dilsel bir amaç için kullanıyor.
DougM

Detaylarla ilgilenirim. Bu durumlarda değişkenlerin gerçekten başlatılmadığından, ancak beyan alanındaki doğrudan programcıdan başka bir şekilde başlatıldığından şüphelenirim. Veya kayıttan çıkarılmadan önce bazı dolaylı yollarla atanırlar.
Karl Bielefeldt

5

Başlatılıyor, başlangıç ​​değerinin önemli olduğu anlamına gelir. Başlangıç ​​değeri önemliyse, evet, açıkça başlatıldığından emin olmalısınız. Önemli değilse, bu daha sonra başlatılacak anlamına gelir.

Gereksiz başlatma, CPU döngüsünün boşa gitmesine neden olur. Bu israf döngüleri belirli programlarda önemli olmasa da, diğer programlarda, hız her zaman önemli olduğundan her döngü önemlidir. Dolayısıyla, kişinin performans hedeflerinin ne olduğunu ve değişkenlerin başlatılması gerekip gerekmediğini anlamak çok önemlidir.

Bellek sızıntıları, bellek bloklarını vermek ve daha sonra geri dönüştürmek için tipik olarak bir bellek ayırıcı işlevini içeren tamamen farklı bir sorundur. Bir postane düşünün. Git ve bir posta kutusu iste. Sana bir tane veriyorlar. Başka bir tane istersin. Size bir tane daha veriyorlar. Kural, bir posta kutusu kullanarak işiniz bittiğinde geri vermeniz gerektiğidir. Geri vermeyi unutursanız, hala sahip olduğunuzu düşünürler ve kutu başka hiç kimse tarafından yeniden kullanılamaz. Dolayısıyla, bağlanan ve kullanılmayan bir bellek yığını var ve bu, bellek sızıntısı olarak adlandırılan şeydir. Bir noktada kutuları sormaya devam ederseniz, hafızanız tükenir. Bunu çok basitleştirdim, ancak temel fikir bu.


-1 bu bağlamda başlatmanın ne anlama geldiğini yeniden tanımlıyorsunuz.
Pieter B

@ Bieter B, yorumunu anlamıyorum. Lütfen, nasıl olduğumu söyleyin, "bu bağlamda başlatmanın ne demek olduğunu yeniden tanımlayın". Eyvallah
Eliptik görünüm

Kendi cümlenizi okuyun, döngüsel akıl yürütme: "Başlatılıyor, başlangıç ​​değerinin önemli olduğunu ima eder. Başlangıç ​​değeri önemliyse, evet, açıkça başlatıldığından emin olmalısınız. Önemli değilse, bu, başlatıldı. "
Pieter B

@Bieter B, Bazı insanlar programlı bir sebepten ziyade genel bir kural olarak başlarlar, yani başlangıç ​​değerinin önemli olup olmadığını başlatırlar. OQ'nun kalbi bu değil mi: Bir değişkeni başlatmak ne kadar önemli? Her neyse, buraya oy verdiniz.
Eliptik görünüm

2

Diğerlerinin söylediği gibi, dile bağlıdır. Ama değişkenleri başlatma hakkındaki Java (ve Etkili Java) fikirlerimi göstereceğim. Bunlar diğer birçok üst düzey dil için kullanılabilir olmalıdır.

Sabitler ve sınıf değişkenleri

staticJava ile işaretlenmiş sınıf değişkenleri sabitler gibidir. Bu değişkenler normal olarak sonlandırılmalı ve =sınıf başlatıcı bloğu kullanılarak veya içinden tanımlamanın hemen ardından başlatılmalıdır static { // initialize here }.

Alanlar

Birçok üst düzey ve komut dosyası dilinde olduğu gibi alanlara otomatik olarak varsayılan bir değer atanacaktır. Sayılar için ve charbu sıfır değeri olacaktır. Dizeler ve diğer nesneler için null. Şimdi nulltehlikelidir ve idareli kullanılmalıdır. Dolayısıyla bu alanlar mümkün olan en kısa sürede geçerli bir değere ayarlanmalıdır. Yapıcı normalde bunun için mükemmel bir yerdir. Değişkenlerin kurucu sırasında ayarlandığından ve daha sonra değiştirilmediğinden emin olmak için bunları finalanahtar kelimeyle işaretleyebilirsiniz .

nullBir tür bayrak veya özel değer olarak kullanma isteğine direnmeye çalışın . Örneğin, belirli bir alanı tutmak için durum eklemek daha iyidir. Numaralandırmanın statedeğerlerini kullanan bir alan adı Stateiyi bir seçim olacaktır.

Yöntem parametreleri

Parametrelerin değerlerindeki değişiklikler (nesnelere veya tamsayılar gibi temel türlere atıfta bulunulması gibi) arayan tarafından görülmeyeceğinden, parametreler olarak işaretlenmelidir final. Bu, değişkenin kendisinin değerlerinin değiştirilemeyeceği anlamına gelir. Değeri, söz konusu Not kesilebilir nesne örnekleri olabilir değiştirilebilir, referans farklı nesne ya da işaret etmek değiştirilemez nullolsa.

Yerel değişkenler

Yerel değişkenler otomatik olarak başlatılmaz; değerlerinin kullanılabilmesi için önce başlatılması gerekir. Değişkeninizin başlatıldığından emin olmanın bir yolu, bunları doğrudan bir tür varsayılan değere başlatmaktır. Bu ancak gereken bir şeydir değil yapmak. Çoğu zaman varsayılan değer beklediğiniz bir değer değildir.

Değişkeni yalnızca değişkene tam olarak ihtiyaç duyduğunuz yerde tanımlamak çok daha iyidir. Değişken yalnızca tek bir değer alacaksa (bu, iyi koddaki çoğu değişken için geçerlidir), değişkeni işaretleyebilirsiniz final. Bu, yerel değişkenin sıfır kez veya iki kez değil, tam olarak bir kez atanmasını sağlar. Bir örnek:

public static doMethod(final int x) {
    final int y; // no assignment yet, it's final so it *must* be assigned
    if (x < 0) {
        y = 0;
    } else if (x > 0) {
        y = x;
    } else {
        // do nothing <- error, y not assigned if x = 0
        // throwing an exception here is acceptable though
    }
}

Bir değişken kullanılmadan önce başlatılmazsa, birçok dilin sizi uyaracağını unutmayın. Gereksiz yere endişelenip endişelenmediğinizi görmek için dil özelliklerini ve forumları kontrol edin.


1

Başlatan değişkenlerle ilgili bir sorun yoktur.

Sorun yalnızca henüz yazılmamış bir değişkeni okuduğunuzda ortaya çıkar.

Derleyiciye ve / veya değişken türüne bağlı olarak, başlatma uygulama başlangıcında gerçekleştirilir. Ya da değil.

Otomatik başlatmaya güvenmemek yaygın bir uygulamadır.


0

Değişkenleri başlatmak (örtülü veya açık olarak) çok önemlidir. Bir değişkenin başlatılmaması her zaman bir hatadır (bununla birlikte örtük olarak başlatılabilir. Aşağıya bakınız). C # derleyicisi gibi modern compliers (örnek olarak) bunu bir hata olarak ele alır ve kodu yürütmenize izin vermez. Başlatılmamış bir değişken basitçe işe yaramaz ve zararlıdır. Rastgele bir sayı üreteci oluşturmadığınız sürece, bir kod parçasından belirleyici ve tekrarlanabilir bir sonuç üretmesini beklersiniz. Bu ancak başlatılmış değişkenlerle çalışmaya başlarsanız elde edilebilir.

Gerçekten ilginç olan soru, bir değişkenin otomatik olarak başlatılıp başlatılmadığı ya da manuel olarak yapılması gerekip gerekmediğidir. Kullanılan dile bağlıdır. Örneğin C # 'da, alanlar, yani sınıf düzeyindeki "değişkenler" her zaman otomatik olarak bu değişken türü için varsayılan değere başlatılır default(T). Bu değer, tüm sıfırlardan oluşan bir bit modeline karşılık gelir. Bu, dil spesifikasyonunun bir parçasıdır ve sadece dilin uygulanmasının teknik bir detayı değildir. Bu nedenle güvenle ona güvenebilirsiniz. Bir dil açıkça belirtildiğinde (ve yalnızca) belirtim örtük olarak başlatıldığını belirtiyorsa, bir değişkenin başlatılmaması güvenlidir.Başka bir değer istiyorsanız, değişkeni açıkça başlatmanız gerekir. Ancak; C # yerel değişkenlerde, yani değişkenler ilan yöntemlerde, olan değil , otomatik olarak başlatılır ve her zaman açıkça değişkeni başlatmak gerekir.


2
bu C # 'a özgü bir soru değildir.
DougM

@DougM: Biliyorum. C # 'a özel cevap değil, sadece C #' ı örnek aldım.
Olivier Jacot-Descombes

Tüm diller değişkenlerin açıkça başlatılmasını gerektirmez. "Başlatma işlemi her zaman bir hatadır" ifadeniz yanlıştır ve eldeki soruya netlik eklemez. cevabınızı gözden geçirmek isteyebilirsiniz.
DougM

@DougM: "Gerçekten ilginç olan soru, bir değişkenin otomatik olarak başlatılıp başlatılmadığı ya da manuel olarak yapılması gerekip gerekmediğidir".
Olivier Jacot-Descombes

paragrafın ortasına yarıya gömülmüş olanı mı kastediyorsun? Evet. Daha belirgin hale getirmeli ve "her zaman" iddianıza bir niteleyici eklemeliydiniz.
DougM
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.