C ++: Berapa ukuran objek dari kelas kosong?

111

Saya bertanya-tanya apa yang bisa menjadi ukuran objek dari kelas kosong . Ini pasti tidak boleh 0 byte karena harus memungkinkan untuk referensi dan menunjuk ke sana seperti objek lain. Tapi, seberapa besar benda seperti itu?

Saya menggunakan program kecil ini:

#include <iostream>
using namespace std;

class Empty {};

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

Output yang saya dapatkan pada kompiler Visual C ++ dan Cygwin-g ++ adalah 1 byte ! Ini sedikit mengejutkan saya karena saya mengharapkannya seukuran kata mesin (32 bit atau 4 byte).

Adakah yang bisa menjelaskan mengapa ukuran 1 byte? Mengapa tidak 4 byte? Apakah ini tergantung pada kompiler atau mesin juga? Juga, dapatkah seseorang memberikan alasan yang lebih meyakinkan mengapa objek kelas kosong tidak berukuran 0 byte?

Ashwin Nanjappa
sumber
Saya tidak melihat alasan mengapa itu tidak bisa nol. Tetapi dengan memberinya ukuran, hal-hal lain menjadi lebih mudah di kompiler. Jika Anda memiliki array dari hal-hal ini, maka setiap elemen membutuhkan alamat yang unik. Ukuran 1 membuatnya mudah.
Martin York
2
Ini bisa berukuran nol jika itu adalah subobjek kelas dasar.
Johannes Schaub - litb

Jawaban:

129

Mengutip FAQ Teknik dan Gaya C ++ dari Bjarne Stroustrup , alasan ukurannya bukan nol adalah "Untuk memastikan bahwa alamat dari dua objek yang berbeda akan berbeda." Dan ukurannya bisa 1 karena kesejajaran tidak penting di sini, karena tidak ada yang benar-benar perlu dilihat.

Sol
sumber
55
Bah, apa sih yang dia ketahui tentang C ++? :-)
paxdiablo
18
@Lazer, karena tidak ada struct kosong di C.
aib
7
@nurabha Penunjuk ini menunjuk ke objek. Itu tidak disimpan di objek. Namun, jika ada fungsi virtual, objek berisi penunjuk ke vtable.
tbleher
4
@krish_oza: menurutmu salah. Ketika Anda mengalokasikan variabel di stack, itu tidak dapat menempati nol byte (karena variabel yang berbeda membutuhkan alamat yang berbeda), maka ukurannya 1 minimum. Setelah itu, terserah kompilernya. Demikian pula dengan new; ketika ruang dialokasikan, alokasi lain harus memiliki alamat yang berbeda. Dan seterusnya. Belum tentu ada pointer yang terlibat dalam kelas kosong; mungkin ada petunjuk ke variabel (atau referensi, atau alokasi lokal / tumpukan), tetapi ukurannya tidak nol dan belum tentu ukuran penunjuk.
Jonathan Leffler
3
@Destructor, tidak pintar tapi saya tahu apa itu smiley :-) Anda mungkin ingin membaca kembali komentar tersebut dan menyadari bahwa itu adalah humor.
paxdiablo
30

Standar menyatakan bahwa semua objek turunan memiliki sizeof ()> = 1:

Kecuali itu adalah bit-field (class.bit), objek yang paling diturunkan harus memiliki ukuran bukan nol dan harus menempati satu atau lebih byte penyimpanan. Sub-objek kelas dasar mungkin memiliki ukuran nol. ISO / IEC FDIS 14882: 1998 (E) intro.object

TrayMan
sumber
1
Saya merasa sulit untuk percaya. Standar berusaha keras untuk memastikan implementasi memiliki kebebasan untuk melakukan pekerjaan pengoptimalan dengan baik yang mengikat tangan pelaksana seperti itu tidak terdengar seperti hal yang biasanya dilakukan standar (saya bisa saja salah)
Martin York
4
@eSKay - Ini diperlukan agar objek yang berbeda mendapatkan alamat yang berbeda. Anda tidak boleh memiliki peta penunjuk ke objek, misalnya, jika instance yang berbeda memiliki alamat yang sama.
Brian Neal
14

Itu benar-benar detail implementasi. Dahulu kala, saya pikir itu bisa menjadi nol byte atau seribu byte, yang tidak ada hubungannya dengan spesifikasi bahasa. Tetapi, setelah melihat standar (bagian 5.3.3), sizeofdidefinisikan sebagai selalu mengembalikan satu atau lebih besar, tidak peduli apa.

Ukuran kelas yang paling banyak diturunkan harus lebih besar dari nol.

Ini diperlukan untuk, antara lain, memungkinkan Anda menangani array objek dan pointer ke sana. Jika elemen Anda dibiarkan berukuran nol maka &(array[0])akan identik dengan &(array[42]), yang akan menyebabkan segala macam malapetaka pada loop pemrosesan Anda.

Alasan mengapa ini mungkin bukan kata mesin adalah karena tidak ada elemen di dalamnya yang benar-benar memerlukannya untuk disejajarkan pada batas kata (seperti integer). Misalnya, jika Anda menempatkan char x; int y;di dalam kelas, GCC saya mencatatnya pada delapan byte (karena int kedua harus selaras dalam implementasi itu).

paxdiablo
sumber
Alasan untuk "bukan nol" adalah bahwa objek yang berbeda harus memiliki alamat yang berbeda. Bayangkan sebuah array objek berukuran nol. Bagaimana Anda mengindeksnya? Dalam beberapa kasus, kompilator diizinkan untuk mengoptimalkan ini jauh (pengoptimalan kelas dasar kosong)
jalf
@jalf: "Bagaimana Anda mengindeksnya?" Cara yang sama akan saya lakukan di C (untuk array objek struct, misalnya) ??
Lazer
1
@eSKay - Anda tidak bisa jika mereka memiliki 0 ukuran. Mereka semua akan berada di elemen 0.
Brian Neal
1
@BrianNeal yang tidak masalah, karena mereka tidak memiliki status untuk membedakan diri. Masalah hanya akan muncul jika Anda mempertimbangkan petunjuk.
gha.
2
Atau mengambil ukuran larik tersebut untuk menghitung panjangnya.
gha.
6

Ada pengecualian: array dengan panjang 0

#include <iostream>

class CompletlyEmpty {
  char NO_DATA[0];
};

int main(int argc, const char** argv) {
  std::cout << sizeof(CompletlyEmpty) << '\n';
}
Konstantin Nikitin
sumber
Mengapa tidak ada yang mengomentari jawaban ini? Sepertinya sangat penasaran bagi saya.
Peregring-lk
Jika Anda membuat dua objek "CompletelyEmpty" (misalnya, 'a' dan 'b'), sizeof menyatakan panjangnya 0 byte, tetapi alamatnya berbeda ('& a == & b' mengevaluasi false). Dan ini seharusnya tidak mungkin ... (menggunakan g ++ 4.7.2).
Peregring-lk
1
Tetapi jika Anda membuat larik objek ini, katakanlah c, &c[M] == &c[N]untuk setiap Mdan N(clang ++ 4.1).
Konstantin Nikitin
5
C dan C ++ tidak mengizinkan array dengan panjang nol. Kompiler Anda bisa, tapi itu salah.
Konrad Borowski
ya, ukuran Kelas itu sendiri adalah nol, tetapi turunan dari kelas ini masih 1 byte.
ZeR0
5

Meskipun tidak diharuskan untuk menetapkan memori apapun untuk kelas kosong, namun untuk membuat objek kelas kosong, compiler memberikan memori minimum yang dapat ditetapkan, yaitu 1 byte. Dengan cara ini kompilator dapat membedakan dua objek dari kelas kosong yang sama secara unik, dan akan dapat menetapkan alamat objek ke penunjuk tipe kelas kosong.

lalatendu
sumber
3

Ini dapat membantu Anda :-) http://bytes.com/topic/c/insights/660463-sizeof-empty-class-structure-1-a

Ukuran kelas atau struktur kosong adalah 1

Alasan hal ini terjadi bermuara pada penerapan standar dengan benar, salah satu hal yang dikatakan standar C ++ adalah bahwa "tidak ada objek yang memiliki alamat yang sama dalam memori seperti variabel lainnya" .... Apa cara termudah untuk memastikan ini? Pastikan semua jenis memiliki ukuran bukan nol. Untuk mencapai hal ini, kompilator menambahkan byte dummy ke struktur dan kelas yang tidak memiliki anggota data dan tidak memiliki fungsi virtual sehingga mereka memiliki ukuran 1 daripada 0 dan kemudian dijamin memiliki alamat memori yang unik.

Arsalan Mehmood
sumber
2

Alokasi 1 byte untuk kelas kosong bergantung pada compiler. Kompiler perlu memastikan objek berada di lokasi memori yang berbeda dan mereka perlu mengalokasikan ukuran memori bukan nol ke objek. Dengarkan catatan tentang topik ini di sini: http://listenvoice.com/listenVoiceNote.aspx?id=27

Meskipun compiler mengalokasikan ukuran bukan nol ke kelas kosong, mereka juga melakukan pengoptimalan saat kelas baru diturunkan dari kelas kosong. Dengarkan tentang pengoptimalan basis kosong pada pertanyaan wawancara pemrograman c ++ ListenVoice.

pengguna332764
sumber
2

alasan kelas yang tidak memiliki anggota data tetapi berukuran 1 byte adalah karena * teks yang kuat * ini harus disimpan dalam memori agar referensi atau penunjuk dapat menunjuk ke objek kelas tersebut

Ramiz
sumber
0

kelas kosong -kelas itu tidak berisi konten apa pun.

setiap kelas yang tidak kosong akan diwakili oleh isinya dalam memori.

sekarang bagaimana kelas kosong akan direpresentasikan dalam memori? karena tidak memiliki konten, tidak ada cara untuk menunjukkan keberadaannya dalam memori, tetapi kelas hadir, maka wajib menunjukkan keberadaannya dalam memori. Untuk menunjukkan keberadaan kelas kosong di memori, diperlukan 1 byte.

Ganesh
sumber
0

Saya rasa demikian karena 1 byte adalah unit memori terkecil yang dapat digunakan sebagai placeholder, dan tidak dapat memberikan ukuran nol karena tidak mungkin membuat array objek ..

dan hal yang Anda katakan "Ini sedikit mengejutkan saya karena saya mengharapkannya seukuran kata mesin (32 bit atau 4 byte)." akan benar untuk variabel referensi (kata-kata macine) tipe kosong (), bukan ukuran kelas itu sendiri (yang merupakan tipe data abstrak),

lazarus
sumber
0

Saya pikir pertanyaan ini hanya untuk kepentingan teoritis tetapi tidak masalah dalam praktiknya.

Seperti yang telah ditunjukkan oleh orang lain, berasal dari kelas kosong tidak membahayakan, karena ini tidak akan menghabiskan memori tambahan untuk bagian kelas dasar.

Selain itu, jika sebuah kelas kosong (artinya - secara teoritis - tidak memerlukan memori per-instance, yaitu tidak memiliki anggota data non-statis atau fungsi anggota virtual) maka semua fungsi anggotanya juga dapat (dan harus) didefinisikan sebagai statis. Jadi tidak perlu membuat instance dari kelas ini.

Intinya: Jika Anda menemukan diri Anda menulis kelas X yang kosong maka cukup buat semua fungsi anggota statis. Kemudian Anda tidak perlu membuat objek X, dan kelas turunan tidak akan terpengaruh dengan cara apa pun.

kidfisto
sumber
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;
    }

Output: Oke tidak masalah memiliki alamat yang berbeda

Mengembalikan ukuran 1 memastikan bahwa kedua objek tidak akan memiliki alamat yang sama.

Sandeep_black
sumber
0

Ini bukan nol untuk memastikan bahwa dua objek yang berbeda akan memiliki alamat yang berbeda. Objek yang berbeda harus memiliki alamat yang berbeda, sehingga ukuran kelas kosong selalu 1 byte.

Yadvendra Yadav
sumber
-2

Saya pikir jika ukuran kelas kosong adalah nol itu berarti tidak ada. Agar (kelas) ada, itu harus memiliki setidaknya 1 byte, karena byte ini adalah memori / alamat referensi.

Madu
sumber
-3

Karena pointer ini , meskipun pointer adalah (integer) dari 4 byte tetapi mengacu pada satu lokasi memori (satu unit) yaitu 1 byte.

Narayan das khatri
sumber
5
Maaf, tapi ini tidak masuk akal.
jogojapan
@Narayan das khatri: pertama jenis pointer tergantung pada tipe datanya tidak selalu int dan kedua ukuran pointer tergantung pada mesin dan kompiler pada mesin 32 bit adalah 4 byte dan untuk mesin 64 bit adalah 8 byte.
Krishna Oza