C ++: Boş bir sınıfın nesnesinin boyutu nedir?


111

Boş bir sınıftaki nesnenin boyutunun ne olabileceğini merak ediyordum . Elbette 0 bayt olamaz, çünkü başka herhangi bir nesne gibi ona başvurmak ve işaret etmek mümkün olmalıdır. Ama böyle bir nesne ne kadar büyük?

Bu küçük programı kullandım:

#include <iostream>
using namespace std;

class Empty {};

int main()
{
    Empty e;
    cerr << sizeof(e) << endl;
    return 0;
}

Hem Visual C ++ hem de Cygwin-g ++ derleyicilerinde aldığım çıktı 1 bayttı ! Makine kelimesinin boyutunda (32 bit veya 4 bayt) olmasını beklediğim için bu benim için biraz şaşırtıcıydı.

1 bayt büyüklüğünün neden olduğunu kimse açıklayabilir mi? Neden 4 bayt değil ? Bu derleyiciye mi yoksa makineye mi bağlı? Ayrıca, boş bir sınıf nesnesinin neden 0 bayt boyutunda olmayacağına dair daha ikna edici bir neden var mı?


Sıfır olmaması için hiçbir sebep göremiyorum. Ancak ona bir boyut vererek derleyicide işler daha kolay hale gelir. Bunlardan oluşan bir diziye sahipseniz, her elemanın benzersiz bir adrese ihtiyacı vardır. 1 boyutu bunu kolaylaştırır.
Martin York

2
Temel sınıf alt nesnesiyse sıfır boyutlu olabilir.
Johannes Schaub - litb

Yanıtlar:


129

Bjarne Stroustrup'un C ++ Stili ve Tekniği SSS'sinden alıntı yaparsak , boyutun sıfır olmamasının nedeni "İki farklı nesnenin adreslerinin farklı olmasını sağlamak için" dir. Ve boyut 1 olabilir, çünkü burada gerçekten bakılacak hiçbir şey olmadığı için hizalama önemli değildir.


55
Bah, C ++ hakkında ne anlar ki? :-)
paxdiablo

18
@Lazer, çünkü C'de boş yapı yok
aib

7
Bu işaretçi noktaları @nurabha için nesne. Nesnede depolanmaz. Bununla birlikte, sanal işlevler varsa, nesne vtable'a bir işaretçi içerir.
tbleher

4
@krish_oza: Yanlış düşünüyorsun. Yığın üzerine bir değişken ayırdığınızda, sıfır bayt işgal edemez (çünkü farklı değişkenler farklı adreslere ihtiyaç duyar), dolayısıyla boyut 1 minimumdur. Bundan sonra, derleyiciye kalmıştır. Benzer şekilde new; alan tahsis edildiğinde, başka bir tahsisin farklı bir adresi olmalıdır. Ve bunun gibi. Boş sınıfa dahil olan herhangi bir gösterici olması gerekmez; değişkenlere (veya referanslara veya yerel / yığın tahsislerine) işaretçiler olabilir, ancak bunlar sıfır boyutta değildir ve zorunlu olarak işaretçi boyutu değildir.
Jonathan Leffler

3
@Destructor, daha zeki değil ama gülen yüzün ne olduğunu biliyorum :-) Yorumu o ışıkta tekrar okumak ve mizah olduğunu fark etmek isteyebilirsiniz.
paxdiablo

30

Standart, türetilmiş nesnelerin çoğunun sizeof ()> = 1'e sahip olduğunu belirtir:

Bir bit alanı olmadığı sürece (sınıf.bit), en çok türetilen nesne sıfır olmayan bir boyuta sahip olacak ve bir veya daha fazla depolama baytı kaplayacaktır. Temel sınıf alt nesnelerinin boyutu sıfır olabilir. ISO / IEC FDIS 14882: 1998 (E) intro.object


1
Buna inanmakta zorlanıyorum. Standart, uygulamaların iyi bir optimizasyon işi yapmak için serbest bir ele sahip olduğundan emin olmak için kendi yolundan çıkıyor; uygulayıcının ellerini bu şekilde bağlayarak, standart normalde yaptığı gibi görünmüyor (yanılıyor olabilirim)
Martin York

4
@eSKay - Bu, farklı nesnelerin farklı adresler alması için gereklidir. Örneğin, farklı örnekler aynı adrese sahipse, nesnelere işaretçilerin bir haritasına sahip olamazsınız.
Brian Neal

14

Bu gerçekten bir uygulama detayı. Uzun zaman önce, sıfır bayt veya bin bayt olabileceğini, dil spesifikasyonuyla ilgisi olmadığını düşünmüştüm. Ancak, standarda baktıktan sonra (bölüm 5.3.3), sizeofne olursa olsun, her zaman bir veya daha fazlasını döndürmek olarak tanımlanır.

En çok türetilmiş bir sınıfın boyutu sıfırdan büyük olacaktır.

Bu, diğer şeylerin yanı sıra, nesne dizilerini ve bunlara yönelik işaretçileri kullanmanıza izin vermek için gereklidir. Öğelerinizin sıfır boyutlu olmasına izin verildiyse, o &(array[0])zaman aynı olacaktır &(array[42]), bu da işleme döngülerinize her türlü hasara neden olacaktır.

Bunun bir makine kelimesi olmamasının nedeni, içinde aslında bir kelime sınırına (bir tamsayı gibi) hizalanmasını gerektiren hiçbir unsur olmamasıdır. Örneğin char x; int y;, sınıfın içine yerleştirirseniz, benim GCC onu sekiz baytta saatler (çünkü ikinci int bu uygulamada hizalanmalıdır).


"Sıfır olmaması" nın nedeni, farklı nesnelerin farklı adreslere sahip olması gerektiğidir. Sıfır boyutlu nesnelerden oluşan bir dizi düşünün. Nasıl indekslersiniz? Bazı durumlarda, derleyicinin bunu optimize etmesine izin verilir (boş temel sınıf optimizasyonu)
jalf

@jalf: "Nasıl indekslersiniz?" C'de yaptığım gibi (örneğin, bir dizi yapı nesnesi için) ??
Lazer

1
@eSKay - 0 beden olsaydı yapamazdın. Hepsi 0. öğede olacaktı.
Brian Neal

1
@BrianNeal, kendilerini farklılaştıracak devletleri olmadığı için sorun değil. Sorunlar yalnızca işaretçileri dikkate aldığınızda ortaya çıkar.
gha

2
Veya uzunluğunu hesaplamak için adı geçen dizinin boyutunu almak.
gha

6

Bir istisna var: 0 uzunluklu diziler

#include <iostream>

class CompletlyEmpty {
  char NO_DATA[0];
};

int main(int argc, const char** argv) {
  std::cout << sizeof(CompletlyEmpty) << '\n';
}

Neden kimse bu yanıtı yorumlamadı? Benim için çok meraklı görünüyor.
Peregring-lk

İki "CompletelyEmpty" nesnesi (örneğin 'a' ve 'b') oluşturursanız, sizeof 0 bayt uzunluğunda olduklarını söyler, ancak adresleri farklıdır ('& a == & b' yanlış olarak değerlendirilir). Ve bu imkansız olmalı ... (g ++ 4.7.2 kullanarak).
Peregring-lk

1
Ama bu nesneler, diyelim ki, bir dizi oluşturursanız c, &c[M] == &c[N]her için Mve N(çınlama ++ 4.1).
Konstantin Nikitin 13

5
C ve C ++ sıfır uzunluklu dizilere izin vermez. Derleyiciniz yapabilir, ancak bu yanlış.
Konrad Borowski

evet, Sınıf boyutunun kendisi sıfırdır, ancak bu sınıfın bir örneği hala 1 bayttır.
ZeR0

5

Derleyici, boş bir sınıfa herhangi bir bellek atamak zorunda olmasa da, boş sınıflardan nesneler yapmak için, atanabilecek minimum belleği 1 bayt olarak atar. Bu şekilde derleyici, aynı boş sınıftaki iki nesneyi benzersiz bir şekilde ayırt edebilir ve nesnenin adresini boş sınıf türünün bir işaretçisine atayabilir.



3

Bu size yardımcı olabilir :-) http://bytes.com/topic/c/insights/660463-sizeof-empty-class-structure-1-a

Boş bir sınıfın veya yapının boyutu 1

Bunun olmasının nedeni, standardın düzgün bir şekilde uygulanmasına indirgeniyor, C ++ standardının söylediği şeylerden biri, "hiçbir nesnenin bellekte diğer herhangi bir değişkenle aynı adrese sahip olmamasıdır" .... Bunu sağlamanın en kolay yolu nedir? Tüm türlerin sıfır olmayan bir boyuta sahip olduğundan emin olun. Bunu başarmak için derleyici, veri üyesi olmayan ve sanal işlevi olmayan yapılara ve sınıflara, 0 boyutundan ziyade 1 boyutuna sahip olacakları ve ardından benzersiz bir bellek adresine sahip olmaları garanti edilecek şekilde sahte bir bayt ekler.


2

Boş bir sınıf için 1 bayt ayrılması derleyiciye bağlıdır. Derleyicilerin, nesnelerin farklı bellek konumlarında bulunduğundan emin olmaları ve bir nesneye sıfır olmayan bellek boyutu tahsis etmeleri gerekir. Bu konuyla ilgili notları buradan dinleyin: http://listenvoice.com/listenVoiceNote.aspx?id=27

Derleyiciler sıfır olmayan bir boyutu boş bir sınıfa ayırsa da, yeni sınıflar boş sınıflardan türetildiğinde optimizasyonlar da yaparlar. ListenVoice'un c ++ programlama görüşme soruları hakkındaki boş temel optimizasyonu dinleyin.


2

Veri üyelerine sahip olmayan ancak 1 bayt boyutuna sahip sınıfın nedeni, bu * güçlü metnin * bellekte saklanması gerektiğidir, böylece bir referans veya işaretçi o sınıfın nesnesine işaret edebilir


0

boş sınıf -bu sınıf herhangi bir içerik içermiyor.

boş olmayan herhangi bir sınıf, hafızadaki içeriği ile temsil edilecektir.

şimdi bellekte ne kadar boş sınıf temsil edilecek? hafızadaki varlığını gösterme içeriği olmadığı için, sınıf mevcut olduğundan, varlığını hafızada göstermesi zorunludur. Hafızadaki boş sınıf varlığını göstermek için 1 bayt gereklidir.


0

Bence öyle çünkü 1 bayt yer tutucu olarak kullanılabilecek en küçük bellek birimi olduğundan ve bir dizi nesne oluşturmak mümkün olmayacağı için sıfır boyut veremez ..

ve söylediğiniz şey "Bu benim için biraz şaşırtıcıydı çünkü bunun makine kelimesinin boyutunda olmasını bekliyordum (32 bit veya 4 bayt)." boş () türündeki referans değişkeni (macine sözcükleri) için doğru olacaktır, sınıfın boyutu değil (soyut veri türü),


0

Bence bu soru sadece teorik bir ilgi ama pratikte önemli değil.

Başkalarının da belirttiği gibi, boş bir sınıftan türetmek herhangi bir zarar vermez, çünkü bu, temel sınıf kısmı için fazladan bellek tüketmez.

Dahası, eğer bir sınıf boşsa (yani teorik olarak - örnek başına belleğe ihtiyaç duymuyorsa, yani statik olmayan veri üyelerine veya sanal üye işlevlerine sahip değilse) o zaman tüm üye işlevleri de aynı şeyi yapabilir (ve statik olarak tanımlanmalıdır). Bu nedenle, bu sınıfın bir örneğini oluşturmaya gerek yoktur.

Sonuç olarak: Kendinizi boş bir X sınıfı yazarken bulursanız, tüm üye işlevleri statik hale getirin. Daha sonra X nesneleri oluşturmanız gerekmeyecek ve türetilmiş sınıflar hiçbir şekilde etkilenmeyecektir.


0
#include<iostream>
using namespace std;


    class Empty { };
    int main()
    {
        Empty* e1 = new Empty;
        Empty* e2 = new Empty;

        if (e1 == e2)
            cout << "Alas same address of two objects" << endl;
        else
            cout << "Okay it's Fine to have different addresses" << endl;

        return 0;
    }

Çıktı: Tamam, farklı adreslere sahip olmak sorun değil

Boyut 1'in döndürülmesi, iki nesnenin aynı adrese sahip olmamasını sağlar.


0

İki farklı nesnenin farklı adreslere sahip olmasını sağlamak sıfırdan farklıdır. Farklı nesnelerin farklı adresleri olmalıdır, bu nedenle boş bir sınıfın boyutu her zaman 1 bayttır.


-2

Bence boş bir sınıfın boyutu sıfırsa, bu sınıfın olmadığı anlamına gelir. Onun (sınıfın) var olması için en az 1 bayta sahip olması gerekir, çünkü bu bayt bellek / referans adresidir.


-3

Bu nedenle, böyle Bu gösterge 4 bayt (tam sayı) olduğu ancak 1 bayt olan bir bellek konumu (bir birim) ile ilgilidir, ancak işaretçi.


5
Üzgünüm ama bu çok saçma.
jogojapan

@Narayan das khatri: ilk olarak göstericinin türü veri türüne bağlıdır, her zaman int değildir ve ikincisi işaretçinin boyutu 32 bit makinelerde makineye ve derleyiciye bağlıdır ve 64 bit makineler için 8 bayttır.
Krishna Oza
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.