"İnt * ptr = int ()" değer başlatma nasıl yasa dışı değildir?


86

Aşağıdaki kod ( buradan alınmıştır ):

int* ptr = int();

Visual C ++ 'da derler ve işaretçiyi değerle başlatır.

Bu nasıl mümkün olabilir? Demek istediğim int(), türde bir nesne verir intve intbir işaretçiye bir işaret atayamıyorum .

Yukarıdaki kod nasıl yasa dışı değildir?


Cevap değil, harika soru! Hiç böyle bir şey görmedim.
Josh

6
İlkel C bir 'yapıcı' olduğundan ++, int()değeri inşa değerini verir intve varsayılan değeri (Ben C ++ 03 Belirtilen şey düşünüyorum) intolduğunu 0. Bu eşdeğerdirint *ptr = 0;
wkl

7
@EmanuelEy: Hayır, herhangi bir sıfır değerli tamsayı sabiti, işaretçilerin gerçekte nasıl uygulandığına bakılmaksızın boş gösterici sabiti olarak kullanılabilir.
Mike Seymour

1
@MooingDuck: NULLSıfır olmayan bir değer olabileceğini söylemedim . Herhangi bir sıfır değerli tamsayı sabiti olabileceğini söyledim (dahil int()).
Mike Seymour

5
@DanielPryden Bu, daha önce farkında olmadığım "nesne" kelimesinin bir kullanımı.
kabarık

Yanıtlar:


110

int()0 değerine sahip sabit bir ifadedir, dolayısıyla boş gösterici sabiti üretmenin geçerli bir yoludur. Sonuçta, bu sadece biraz farklı bir şekildeint *ptr = NULL;


3
+1, sabit ifade biti önemlidir ve en çok oy verilen 2 cevapta eksiktir.
David Rodríguez - dribeas

bu C ++ 0x ile ortadan kalkar mı?
Neil G

@NeilG: Bu, C ++ 11'de aynı kalır, ancak artık yeni kod nullptryerine 0veya NULLkodda kullanabileceğiniz bir de var.
Jerry Coffin

2
@Nils: Kod netliği ve niyetinizi kod aracılığıyla beyan etme. Elbette, C ++ 11 ile, şimdi nullptr kullanmak istiyorsunuz, çünkü bu aynı zamanda karışıma fazladan derleme zamanı kontrollerinin faydasını da sunuyor.
Jamin Grey

3
@Nils, çünkü açıkça 0bir boş gösterici sabiti veya 0 sayısı anlamına gelebilirken nullptr, açık bir boş gösterici sabiti. Ek olarak, Jamin'in dediği gibi, "fazladan derleme zamanı kontrolleri" de vardır. Yazmadan önce düşünmeye çalışın.
Miles Rout

35

Çünkü birbirinin yerine geçebilen int()verim . kendisi olarak tanımlanır C'ın farklı olarak, bir .0NULLNULL0NULL(void *) 0

Bunun bir hata olacağını unutmayın:

int* ptr = int(5);

ve bu hala işe yarayacak:

int* ptr = int(0);

0özel bir sabit değerdir ve bu nedenle bir işaretçi değeri olarak kabul edilebilir. Verimle sürekli ifadeler 0, örneğin, 1 - 1hem de boş işaretçisi sabit olarak izin verilir.


1
Ayrıca, C'nin NULL değerinin de zorunlu olmadığını unutmayın (void *)0. Bu, basitçe "0 değerine sahip bir tamsayı sabit ifadesi veya böyle bir ifade void * türüne dönüştürülmüş" olarak tanımlanmış bir uygulama.
Jerry Coffin

Ben tanımlanmış bir C derleyicisi hiç kullanmadım @JerryCoffin NULLolarak (void*)0; her zaman oldu 0(veya belki 0L). (Ama sonra, C90 (void*)0C'de yasal hale geldiğinde , zaten C ++ kullanıyordum.)
James Kanze

1
@JamesKanze: ubuntu 11.04'te ve kendi linux çeşidimizde libio.h şunları içerir: ubuntu'daki gcc'nin #if !defined(__cplusplus) \n #define NULL ((void*)0) \n #else \n #define NULL (0)mevcut sürümü 4.5, sistemimizdeki 4.0.
David Rodríguez - dribeas

5
" 0özel bir gerçek değerdir" - sadece sabit bir ifade olduğu ve özel değeri 0 (1-1)olduğu için eşit derecede özeldir, aynı zamanda bir boş gösterici sabiti ve bu yüzden de öyledir int(). 0Birebir olma gerçeği yeterlidir, ancak sabit bir ifade olmak için gerekli bir koşul değildir. Gibi bir şey strlen(""), aynı zamanda özel bir değere sahip olmasına rağmen 0, sabit bir ifade değildir ve dolayısıyla boş gösterici sabiti değildir.
Steve Jessop

@SteveJessop: Düzeltme konusunda hemfikirim, bu gerçekten sabit değerle ilgili 0, 0gerçek değil .
Blagovest Buyukliev

18

İfade int(), 0 değeri olan sabit bir varsayılan olarak başlatılmış tamsayı olarak değerlendirilir. Bu değer özeldir: NULL durumuna bir gösterici başlatmak için kullanılır.


2
Bu Jerry'nin cevabında bulunan çok önemli bir ayrıntıyı kaçırıyor: İfadenin 0 değerini vermesi yeterli değil, aynı zamanda sabit bir ifade de olmalı . Bir karşı örnek için with int f() { return 0; }, ifade f()0 değerini verir, ancak bir işaretçiyi başlatmak için kullanılamaz.
David Rodríguez - dribeas

@ DavidRod Rodríguez-dribeas, acelemde mümkün olan en basit terimlerle bir cevap sunmak için o kısmı dışarıda bıraktım. Umarım şimdi kabul edilebilir.
Mark Ransom

13

N3290'dan (C ++ 03 benzer metin kullanır), 4.10 İşaretçi dönüşümleri [dönş. Tr] 1. paragraf (vurgu benimdir):

1 Boş gösterici sabiti, sıfıra veya std :: nullptr_t türünde bir prvalue olarak değerlendirilen tamsayı türünde bir integral sabit ifadesidir (5.19) . Boş gösterici sabiti bir işaretçi tipine dönüştürülebilir; sonuç, bu türün boş işaretçi değeridir ve diğer tüm nesne işaretçisi veya işlev işaretçi tipinden ayırt edilebilir. Böyle bir dönüşüme boş işaretçi dönüşümü denir. [...]

int()tamsayı türünde böyle bir integral sabit ifade prvalue'dur ve sıfır olarak değerlendirilir (bu bir ağız dolusu!) ve bu nedenle bir işaretçi tipini başlatmak için kullanılabilir. Gördüğünüz gibi 0, özel kasalı olan tek integral ifade değildir.


4

İnt bir nesne değildir.

İnanıyorum ki burada olanın int * 'e int () tarafından belirlenen bir hafıza adresini işaret etmesini söylüyorsunuz

yani int () 0 oluşturursa, int * bellek adresi 0'ı gösterir


1
int()Kesinlikle olan bir nesne.
Orbit'te Hafiflik Yarışları

@Tomalak: Öyle olduğunu sanmıyorum. Bu geçici bir sınıf dışı tiptir ve C ++ standardı söz konusu olduğunda bunların nesneler olmadığını söylemekte haklı olduğumu düşünüyorum . Yine de biraz tuhaf, "geçici nesneler" ile ilgili bölüm dikkatlice sadece sınıf türündeki geçiciler hakkında konuşmaya başlıyor, ancak daha sonra bağlayıcı referanslardan bahsediyor ve tabii ki bir referansa bağlanabilirsiniz int(). Tanımlayın int i;, o zaman hiçbir soru ibir nesne değildir.
Steve Jessop

@Steve: Bu konuyla ilgili tartışmayı yalnızca "nesneler" in C ++ 'da bir depolama bölgesi olduğu ve geçicilerin gerçekten depolama alanı olmadığı için bekliyorum, değil mi? 1.8 / 1, geçicileri açıkça listelemiyor, ancak amaç onları dahil etmek için oradaymış gibi geliyor.
Orbit'te Hafiflik Yarışları

1
@Tomalak: evet gerçekten, sınıf dışı türdeki geçiciler, referans almadığınız sürece depolamaya ihtiyaç duymazlar. Gerçi boşver, önemli değil. "Well int bir nesne değildir" ifadesi yalnızca intbir tür olduğu için doğrudur , bir nesne değildir. İster int()bir nesne ya da sadece şey kimseyi etkilemez bir rvalue başka yerde söyledi verir.
Steve Jessop

@Steve: Bu kadar tartışılmaz :)
Orbit'te Hafiflik Yarışları
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.