Bir işaretçiyi NULL
basitçe yazarak kontrol etmemek güvenli mi if(pointer)
yoksa kullanmam gerekiyor if(pointer != NULL)
mu?
NULL
C ++ ' da kullanmamalısınız , çünkü NULL
belirsiz davranışlar verebilecek uygulamaya bağlı makrodur.
Bir işaretçiyi NULL
basitçe yazarak kontrol etmemek güvenli mi if(pointer)
yoksa kullanmam gerekiyor if(pointer != NULL)
mu?
NULL
C ++ ' da kullanmamalısınız , çünkü NULL
belirsiz davranışlar verebilecek uygulamaya bağlı makrodur.
Yanıtlar:
Yapabilirsin; null işaretçisi örtük olarak boole false değerine, null olmayan işaretçiler true değerine dönüştürülür. C ++ 11 standardından, Boole Dönüşümleri bölümü :
Aritmetik, kodlanmamış numaralandırma, işaretçi veya işaretçi ile üye türünün bir ön değeri, bir tür ön değerine dönüştürülebilir
bool
. Sıfır değeri, boş işaretçi değeri veya boş üye işaretçi değeri dönüştürülürfalse
; başka bir değere dönüştürülürtrue
. Bir tür ön değeri, bir tür ön değerinestd::nullptr_t
dönüştürülebilirbool
; elde edilen değerfalse
.
Evet yapabilirdin.
Bu, Boole dönüşüm yan tümcesinde yer alan C ++ standart dönüşümünün bir parçasıdır :
§ 4.12 Boole dönüşümleri
Aritmetik, kodlanmamış numaralandırma, işaretçi ya da işaretçi ile üye türünün bir ön değeri, bool türünün bir ön değerine dönüştürülebilir. Sıfır değeri, null işaretçi değeri veya null üye işaretçi değeri false değerine dönüştürülür; diğer herhangi bir değer true değerine dönüştürülür. Std :: nullptr_t türünün bir ön değeri, bool türünün bir ön değerine dönüştürülebilir; sonuçta ortaya çıkan değer yanlıştır.
Evet yapabilirsin. Aslında kullanmayı tercih ediyorum if(pointer)
çünkü alıştıktan sonra okumak ve yazmak daha kolay.
Ayrıca nullptr
tercih edilen C ++ 11 tanıtıldı NULL
.
if(som_integer)
vs if(some_integer != 0)
tamsayılar da boolean doğru değildir çünkü? Kaçınmayı 0
veya NULL
bir if ifadesinde tercih ederim .
if (pointer)
Kendimi tercih etmeye geldim , ama if (ptr != nullptr)
benim için gayet meşru görünüyor. Öte yandan, ekibimde yazan birini görürsem, if (some_integer)
onları değiştirmesini isterdim if (some_integer != 0)
. Ancak, bu benim tarafımda nispeten keyfi bir tercih değil gibi davranmayacağım - sadece işaretçileri ve tamsayıları aynı şekilde tedavi etmemeyi tercih ederim.
if(isReady)
if(filePtr)
if(serviceNo)
? Kötü değişken isimlerini bilerek yapmak bu durumda pek bir şey ifade etmez. Her neyse, zaten fikrini aldım ve anladım, ama kendi kodlama tarzımı kendim kullanmakta ısrar edebilirim, tamam mı?
Soru cevaplandı, ama puanlarımı eklemek istiyorum.
Her zaman if(pointer)
yerine if(pointer != NULL)
ve if(!pointer)
yerine her zaman tercih edeceğim if(pointer == NULL)
:
Daha az şansı Ben eşitlik onay operatörü yanlış yazılmış ise varsayalım, bir arabası kod yazmak için ==
birlikte =
if(pointer == NULL)
yanlış yazılmış olabilir if(pointer = NULL)
bunu önlemek olacaktır Yani, iyi adildir if(pointer)
.
(Ben de bir cevapta Yoda durumu önerdim , ama bu farklı bir konu)
Benzer şekilde while (node != NULL && node->data == key)
, sadece while (node && node->data == key)
benim için daha belirgin olduğunu yazacağım (kısa devre kullandığını gösterir).
(boolean expression)? true : false
tamamen anlamsız. Ya sentezleme değerlendirir true
veya false
; "doğruysa, bana doğru ver, eğer yanlışsa, bana yanlış ver" der. Kısacası: Bu tamamen boole ifadesinin kendisine eşdeğerdir. Bunun node == NULL
bir boole ifadesi olduğuna dikkat edin . BTW, iki uygulamanız birbirinin tam tersini döndürür. Ya !=
ilkinde ister !
ikincisinde sadece birini istersiniz .
=
yerine karşı olası bir koruma ==
değişkenlerinizi const
mümkün olduğunca yapmaktır . Örneğin, işlevinizi olarak tanımlayabilirsiniz isEmnpy(node* const head) { ... }
ve sonra node = NULL
bunun yerine yanlışlıkla yazdıysanız derleyici işlevi derlemeyi reddeder node == NULL
. Tabii ki bu sadece gerçekten değiştirmeniz gerekmeyen değişkenler için geçerlidir.
T* get() const
yerine operator T*() const
örtülü dönüşüm önlemek için. Ancak bir operator bool() const
.
NULL için açıkça kontrol etmek derleyiciye ne yapmaya çalıştığınıza dair bir ipucu verebilir, ergo daha az hataya eğilimli olmaya yol açar.
Evet yapabilirsin. Değerleri sıfırlarla örtük olarak karşılaştırma yeteneği C'den devralınmıştır ve tüm C ++ sürümlerinde vardır. if (!pointer)
NULL için işaretçileri kontrol etmek için de kullanabilirsiniz .
Boş göstericiler için ilgili kullanım durumları
Dinamik yayınlar. Belirli bir türetilmiş sınıfa bir temel sınıf işaretçisi atamak (yine kaçınmaya çalışmanız gereken, ancak bazen gerekli bulabilecek bir şey) her zaman başarılı olur, ancak türetilmiş sınıf eşleşmezse boş gösterici ile sonuçlanır. Bunu kontrol etmenin bir yolu
Derived* derived_ptr = dynamic_cast<Derived*>(base_ptr);
if(derived_ptr != nullptr) { ... }
(veya tercihen, auto derived_ptr = ...
). Şimdi, bu kötü, çünkü (muhtemelen geçersiz, yani boş) türetilmiş işaretçiyi güvenlik koruma if
bloğunun kapsamı dışında bırakır . C ++ bir if
koşul içinde boole dönüştürülebilir değişkenleri tanıtmanıza izin verdiği için bu gerekli değildir :
if(auto derived_ptr = dynamic_cast<Derived*>(base_ptr)) { ... }
ki bu sadece daha kısa ve kapsam açısından güvenli değil, aynı zamanda niyetinde çok daha açık: ayrı bir if-koşulunda null olup olmadığını kontrol ettiğinizde, okuyucu "tamam, bu yüzden derived_ptr
burada null olmamalıdır ... boş mu? " Tek satırlık sürümü çok açık söylüyor Oysa "güvenle döküm eğer base_ptr
üzere Derived*
, daha sonra için kullanabilirsiniz ...".
Aynı şey, bir işaretçi döndüren diğer olası başarısızlık işlemleri için de işe yarar, ancak IMO genellikle bundan kaçınmalısınız: boost::optional
işaretçilerden ziyade muhtemelen başarısız işlemlerin sonuçları için "kapsayıcı" gibi bir şey kullanmak daha iyidir.
Boş göstericilerle ana kullanım durumu her zaman örtük-dökme tarzı bir varyasyonu olarak yazılmalıdır Yani, ben tutarlılık nedenleriyle 's iyi derdim hep ben savunmak istiyorum yani bu stili kullanan if(ptr)
üzerinde if(ptr!=nullptr)
.
Korkarım ki bir reklamla bitmeliyim: if(auto bla = ...)
sözdizimi aslında bu tür sorunların gerçek çözümüne biraz hantal bir yaklaşımdır : desen eşleştirme . Neden önce bir eylemi zorlarsınız (bir işaretçi yapmak gibi) ve sonra bir hata olabileceğini düşünürsünüz ... Yani, saçma, değil mi? Sanki biraz yiyecek var ve çorba yapmak istiyorsun. Yumuşak bir sebze olursa, suyu çıkarmak için görevinize asistanınıza verirsiniz. Önce ona bakmıyorsun. Patatesiniz varsa, hala yardımcınıza verirsiniz ama başarısızlık notuyla yüzünüze tokatlar. Ah, zorunlu programlama!
Çok daha iyi: Karşılaşabileceğiniz tüm vakaları hemen düşünün. Sonra buna göre hareket edin. Haskell:
makeSoupOf :: Foodstuff -> Liquid
makeSoupOf p@(Potato{..}) = mash (boil p) <> water
makeSoupOf vegetable
| isSoft vegetable = squeeze vegetable <> salt
makeSoupOf stuff = boil (throwIn (water<>salt) stuff)
Haskell ayrıca gerçekten ciddi bir başarısızlık olasılığı olduğunda (ve bir sürü başka şey için) özel araçlara sahiptir: monadlar. Ama bu onları açıklamak için bir yer değil.
⟨/ Advert⟩
if(ptr)
if(ptr != nullptr)
Evet tabi ki! aslında, eğer (pointer) yazmak, (pointer! = NULL) yerine yazmanın daha kolay bir yoludur çünkü: 1. hata ayıklamak kolaydır 2. anlaşılması kolaydır 3. yanlışlıkla ise, NULL değeri tanımlanırsa, o zaman kod çökmez
Evet. Aslında yapmalısın. Bir segmentasyon hatası oluşturup oluşturmadığını merak ediyorsanız , yapmaz.
Diğerleri zaten iyi cevap verdiğinden, her ikisi de değiştirilebilir.
Bununla birlikte, açık ifadeyi kullanmak isteyebileceğiniz bir durum olabileceğinden bahsetmeye değer pointer != NULL
.
Ayrıca bkz. Https://stackoverflow.com/a/60891279/2463963
Evet, bunu her zaman yapabilirsiniz 'EĞER' koşulu yalnızca içindeki koşul gerçekleştiğinde değerlendirilir. C'nin bir boole dönüş türü yoktur ve bu nedenle koşul doğru olduğunda sıfırdan farklı bir değer döndürürken, 'IF' içindeki koşul yanlış olduğunda 0 değerini döndürür. Varsayılan olarak döndürülen sıfır olmayan değer 1'dir. Bu nedenle, her zaman ikincisini tercih ederken, kodu yazmanın her iki yolu da doğrudur.
If-ifadeniz şu şekilde yeniden yazılabilirse , genel bir kural olarak düşünüyorum
const bool local_predicate = *if-expression*;
if (local_predicate) ...
hiçbir uyarıya neden olmayacak şekilde if ifadesi için THAT tercih edilmelidir . ( İşaretçilerden bağımsız olarak bir C ++ 'a eski bir C BOOL
( #define BOOL int
) atadığımda uyarı aldığımı biliyorum bool
.)
"Güvenli mi..?" , dil standardı ve oluşturulan kod hakkında bir sorudur.
"İyi bir uygulama mı?" ifadenin, herhangi bir keyfi insan okuyucu tarafından ifadenin ne kadar iyi anlaşıldığı sorusudur. Bu soruyu soruyorsanız, "güvenli" sürümün gelecekteki okuyucular ve yazarlar için daha az net olduğu anlaşılmaktadır.
0
veya testini yapmak kadar etkili ve sıklıkla tercih edilirnullptr
. (NULL
bir C'ism'dir ve bir başlık dosyası da gerektirir.)