C ++: एक खाली वर्ग की वस्तु का आकार क्या है?


111

मैं सोच रहा था कि एक खाली वर्ग की वस्तु का आकार क्या हो सकता है । यह निश्चित रूप से 0 बाइट्स नहीं हो सकता है क्योंकि इसे किसी अन्य ऑब्जेक्ट की तरह संदर्भ और इंगित करना संभव होना चाहिए। लेकिन, ऐसी वस्तु कितनी बड़ी है?

मैंने इस छोटे कार्यक्रम का उपयोग किया:

#include <iostream>
using namespace std;

class Empty {};

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

विजुअल C ++ और Cygwin-g ++ कंपाइलर दोनों पर मुझे मिला आउटपुट 1 बाइट था ! यह मेरे लिए थोड़ा आश्चर्यचकित करने वाला था क्योंकि मैं इसे मशीन शब्द (32 बिट्स या 4 बाइट्स) के आकार का होने की उम्मीद कर रहा था।

क्या कोई समझा सकता है कि 1 बाइट का आकार क्यों ? 4 बाइट्स क्यों नहीं ? क्या यह कंपाइलर या मशीन पर भी निर्भर है? इसके अलावा, क्या कोई खाली वर्ग वस्तु 0 बाइट्स का नहीं होगा , इसके लिए कोई और अधिक कारण दे सकता है?


मुझे कोई कारण नहीं दिखता कि यह शून्य क्यों नहीं हो सकता। लेकिन इसे एक आकार देकर दूसरों की चीजें कंपाइलर में आसान हो जाती हैं। यदि आपके पास इन चीजों की एक सरणी है, तो प्रत्येक तत्व को एक अद्वितीय पते की आवश्यकता है। 1 का आकार इसे आसान बनाता है।
मार्टिन यॉर्क

2
यदि यह बेस क्लास सबजेक्ट है तो यह शून्य-आकार हो सकता है।
जोहान्स शहाब -

जवाबों:


129

Bjarne Stroustrup के C ++ स्टाइल और टेक्नीक FAQ को उद्धृत करते हुए , इसका कारण गैर-शून्य है "यह सुनिश्चित करने के लिए कि दो अलग-अलग वस्तुओं के पते अलग-अलग होंगे।" और आकार 1 हो सकता है क्योंकि संरेखण यहां कोई मायने नहीं रखता है, क्योंकि वास्तव में देखने के लिए कुछ भी नहीं है।


55
बाह, वह सी ++ के बारे में क्या जानता होगा? :-)
paxdiablo

18
@ लेज़र, क्योंकि सी में कोई खाली
संरचना नहीं है

7
@nurabha यह सूचक ऑब्जेक्ट को इंगित करता है। यह ऑब्जेक्ट में संग्रहीत नहीं है। यदि, हालाँकि, वर्चुअल फ़ंक्शंस हैं, तो ऑब्जेक्ट में वाइबर के लिए पॉइंटर होता है।
17

4
@krish_oza: आप गलत सोचते हैं। जब आप स्टैक पर एक चर आवंटित करते हैं, तो यह शून्य बाइट्स पर कब्जा नहीं कर सकता है (क्योंकि विभिन्न चर को अलग-अलग पते की आवश्यकता होती है), इसलिए आकार 1 न्यूनतम। उसके बाद, यह संकलक पर निर्भर है। इसी तरह से new; जब स्थान आवंटित किया जाता है, तो दूसरे आवंटन में एक अलग पता होना चाहिए। और इसी तरह। जरूरी नहीं कि खाली कक्षा में कोई पॉइंटर शामिल हो; चर (या संदर्भ, या स्थानीय / स्टैक आवंटन) के संकेत हो सकते हैं, लेकिन वे शून्य आकार के नहीं हैं और वे आवश्यक रूप से सूचक आकार नहीं हैं।
जोनाथन लेफ़लर

3
@ डस्टर, चतुर नहीं, लेकिन मुझे पता है कि एक स्माइली क्या है :-) आप उस प्रकाश में टिप्पणी को फिर से पढ़ना चाहते हैं और महसूस कर सकते हैं कि यह हास्य था।
paxdiablo

30

मानक बताता है कि सभी व्युत्पन्न वस्तुओं का आकार ()> = 1 है:

जब तक यह एक बिट-फ़ील्ड (क्लास.बिट) नहीं है, तब तक सबसे अधिक व्युत्पन्न वस्तु का गैर-शून्य आकार होगा और भंडारण के एक या अधिक बाइट्स पर कब्जा कर लेगा। बेस क्लास सब-ऑब्जेक्ट्स का आकार शून्य हो सकता है। ISO / IEC FDIS 14882: 1998 (E) intro.object


1
मेरे लिए इस पर भरोसा करना मुश्किल है। यह सुनिश्चित करने के लिए मानक अपने रास्ते से बाहर चला जाता है कि कार्यान्वयनकर्ता के हाथों को बांधने के लिए अनुकूलन का एक अच्छा काम करने के लिए एक स्वतंत्र हाथ है जैसे कि मानक सामान्य रूप से जिस तरह की चीज करता है वह ध्वनि नहीं करता है (मैं गलत हो सकता है)
मार्टिन यॉर्क

4
@eSKay - यह आवश्यक है ताकि विभिन्न वस्तुओं को अलग-अलग पते मिलें। उदाहरण के लिए, यदि आप अलग-अलग उदाहरणों का एक ही पता है, तो आपके पास ऑब्जेक्ट्स के लिए पॉइंटर्स का नक्शा नहीं हो सकता है।
ब्रायन नील

14

यह वास्तव में एक कार्यान्वयन विवरण है। एक बार पहले, मैंने सोचा कि यह शून्य बाइट्स या एक हजार बाइट्स हो सकता है, इसका भाषा विनिर्देश पर कोई असर नहीं है। लेकिन, मानक (खंड 5.3.3) को देखने के बाद, sizeofहमेशा एक या एक से अधिक रिटर्न के रूप में परिभाषित किया जाता है, चाहे जो भी हो।

सबसे व्युत्पन्न वर्ग का आकार शून्य से अधिक होगा।

यह अन्य चीजों के लिए आवश्यक है, जिससे आप वस्तुओं और बिंदुओं की सरणियों को संभाल सकते हैं। यदि आपके तत्वों को शून्य-आकार की अनुमति दी गई थी, तो &(array[0])इसके समान होगा &(array[42]), जो आपके प्रसंस्करण छोरों के लिए सभी प्रकार के कहर का कारण बनने वाला है।

इसका कारण यह हो सकता है कि यह मशीन शब्द नहीं है, इसके भीतर कोई तत्व नहीं हैं जो वास्तव में इसे शब्द सीमा (जैसे पूर्णांक) पर संरेखित करने की आवश्यकता होती है। उदाहरण के लिए, यदि आप char x; int y;कक्षा के अंदर आते हैं , तो मेरा जीसीसी इसे आठ बाइट्स में देखता है (चूंकि दूसरा इंट को उस कार्यान्वयन में जोड़ा जाना चाहिए)।


"शून्य नहीं" का कारण विभिन्न वस्तुओं के अलग-अलग पते होना चाहिए। शून्य-आकार की वस्तुओं की एक सरणी की कल्पना करें। आप इसे कैसे अनुक्रमित करेंगे? कुछ मामलों में, संकलक हालांकि (खाली आधार वर्ग optmization) की दूरी पर इस अनुकूलन करने के लिए अनुमति दी है
jalf

@jalf: "आप इसे कैसे अनुक्रमित करेंगे?" उसी तरह से मैं सी में करूँगा (उदाहरण के लिए, संरचनात्मक वस्तुओं की एक सरणी के लिए) ??
लेज़र

1
@eSKay - यदि आपके पास 0 आकार नहीं है, तो आप नहीं कर सकते। वे सभी तत्व 0.
ब्रायन नील

1
@BrianNeal कोई समस्या नहीं है, क्योंकि उनके पास खुद को अलग करने के लिए कोई राज्य नहीं है। समस्या केवल तभी आती है जब आप संकेत पर विचार करते हैं।
gha.st

2
या उक्त सरणी का आकार लेते हुए उसकी लंबाई की गणना करना।
gha.st

6

एक अपवाद है: 0-लंबाई सरणियाँ

#include <iostream>

class CompletlyEmpty {
  char NO_DATA[0];
};

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

किसी ने इस जवाब पर टिप्पणी क्यों नहीं की? यह मेरे लिए बहुत उत्सुक लगता है।
पीरग्रेडिंग-एलके

यदि आप दो "कंप्लीटली खाली" ऑब्जेक्ट (उदाहरण के लिए '' a 'और' b ') बनाते हैं, तो sizeof का कहना है कि वे 0 बाइट्स लंबे हैं, लेकिन इसके पते अलग-अलग हैं (' & a == & b 'गलत का मूल्यांकन करता है)। और यह असंभव होना चाहिए ... (जी ++ 4.7.2 का उपयोग करके)।
पेरेग्रिंग-एलके

1
लेकिन अगर आप इस ऑब्जेक्ट की एक सरणी बनाते हैं, तो c, &c[M] == &c[N]हर Mऔर N(clang ++ 4.1) के लिए कहें ।
कॉन्स्टेंटिन निकितिन

5
C और C ++ शून्य-लंबाई सरणियों की अनुमति नहीं देता है। आपका कंपाइलर, लेकिन यह गलत है।
कोनराड बोरोस्की

हां, कक्षा का आकार स्वयं शून्य है, लेकिन इस वर्ग का एक उदाहरण अभी भी 1 बाइट है।
ZeR0

5

भले ही इसके लिए किसी खाली वर्ग के लिए कोई मेमोरी असाइन करने की आवश्यकता नहीं है, लेकिन खाली कक्षाओं की वस्तुओं को बनाने के लिए, कंपाइलर उस न्यूनतम मेमोरी को असाइन करता है जिसे असाइन किया जा सकता है, जो कि 1 बाइट है। इस तरह संकलक एक ही खाली वर्ग की दो वस्तुओं को विशिष्ट रूप से अलग कर सकता है, और वस्तु के पते को खाली वर्ग प्रकार के एक पॉइंटर को निर्दिष्ट करने में सक्षम होगा।



3

इससे u :-) http://bytes.com/topic/c/insights/660463-sizeof-empty-class-structure-1-a मदद मिल सकती है

एक खाली वर्ग या संरचना का आकार 1 है

ऐसा होने का कारण यह है कि मानक को ठीक से लागू करने के लिए फोड़ा जाता है, सी ++ मानक में से एक बात यह है कि "किसी भी वस्तु का स्मृति में किसी अन्य चर के समान पता नहीं होगा" .... यह सुनिश्चित करने का सबसे आसान तरीका क्या है? सुनिश्चित करें कि सभी प्रकारों में एक गैर-शून्य आकार है। इसे प्राप्त करने के लिए संकलक संरचनाओं और कक्षाओं में एक डमी बाइट जोड़ता है, जिसमें कोई डेटा सदस्य नहीं है और कोई वर्चुअल फ़ंक्शन नहीं है, ताकि उनके पास 0 के आकार के बजाय 1 का आकार हो और फिर उन्हें एक अद्वितीय मेमोरी पता होने की गारंटी हो।


2

एक खाली वर्ग के लिए 1 बाइट का आवंटन संकलक पर निर्भर है। कंपाइलरों को यह सुनिश्चित करने की आवश्यकता होती है कि ऑब्जेक्ट अलग-अलग मेमोरी लोकेशन में रहते हैं और उन्हें किसी वस्तु को नॉन जीरो मेमोरी साइज आवंटित करने की आवश्यकता होती है। इस विषय पर नोट्स यहाँ सुनें: http://listenvoice.com/listenVoiceNote.aspx?id=27

हालांकि संकलक एक शून्य वर्ग को एक खाली वर्ग आवंटित करते हैं, वे भी तब अनुकूलन करते हैं जब नई कक्षाएं खाली कक्षाओं से ली जाती हैं। ListenVoice के c ++ प्रोग्रामिंग इंटरव्यू प्रश्नों पर खाली आधार अनुकूलन के बारे में सुनें।


2

बिना डेटा सदस्यों वाले वर्ग का कारण लेकिन आकार 1 बाइट यह है कि यह * मजबूत पाठ * स्मृति में संग्रहीत किया जाना चाहिए ताकि एक संदर्भ या सूचक उस वर्ग के ऑब्जेक्ट को इंगित कर सके


0

खाली वर्ग -that वर्ग में कोई सामग्री नहीं है।

कोई भी वर्ग जो खाली नहीं है, उसकी सामग्री को स्मृति में दर्शाया जाएगा।

अब कैसे खाली वर्ग का प्रतिनिधित्व स्मृति में किया जाएगा? क्योंकि इसमें मेमोरी में अपनी मौजूदगी दिखाने का कोई तरीका नहीं है, लेकिन क्लास मौजूद है, इसलिए मेमोरी में अपनी उपस्थिति दिखाना अनिवार्य है। स्मृति में खाली वर्ग की उपस्थिति दिखाने के लिए 1 बाइट की आवश्यकता होती है।


0

मुझे लगता है कि ऐसा इसलिए है क्योंकि 1 बाइट सबसे छोटी मेमोरी यूनिट है जिसे प्लेसहोल्डर के रूप में इस्तेमाल किया जा सकता है, और यह शून्य आकार नहीं दे सकता क्योंकि यह ऑब्जेक्ट्स की एक सरणी बनाने के लिए संभव नहीं होगा।

और आपने जो बात कही, "यह मेरे लिए थोड़ा आश्चर्यचकित करने वाला था क्योंकि मैं उम्मीद कर रहा था कि यह मशीन के आकार (32 बिट्स या 4 बाइट्स) के आकार का होगा।" प्रकार के रिक्त () के संदर्भ चर (macine शब्द) के लिए सही होगा, वर्ग के आकार का नहीं (जो कि सार डेटा प्रकार है),


0

मुझे लगता है कि यह सवाल केवल सैद्धांतिक हित का है लेकिन व्यवहार में मायने नहीं रखता।

जैसा कि पहले ही दूसरों ने बताया है, एक खाली वर्ग से प्राप्त करने से कोई नुकसान नहीं होता है, क्योंकि यह बेस क्लास हिस्से के लिए किसी भी अतिरिक्त मेमोरी का उपभोग नहीं करेगा।

इसके अलावा, यदि कोई वर्ग खाली है (इसका अर्थ है कि यह - सैद्धांतिक रूप से - किसी भी प्रति-मेमोरी मेमोरी की आवश्यकता नहीं है, अर्थात इसमें कोई गैर-स्थैतिक डेटा सदस्य या वर्चुअल सदस्य फ़ंक्शन नहीं हैं) तो इसके सभी सदस्य कार्य बस के रूप में अच्छी तरह से कर सकते हैं (और चाहिए) को स्थिर के रूप में परिभाषित किया जाना चाहिए। इसलिए कभी भी इस वर्ग का एक उदाहरण बनाने की आवश्यकता नहीं है।

नीचे पंक्ति: यदि आप अपने आप को एक खाली कक्षा X लिखते हुए पाते हैं, तो बस सभी सदस्य कार्यों को स्थिर बनाएं। फिर आपको एक्स ऑब्जेक्ट बनाने की आवश्यकता नहीं होगी, और व्युत्पन्न कक्षाएं किसी भी तरह से प्रभावित नहीं होंगी।


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

आउटपुट: ठीक है, अलग-अलग पते होना ठीक है

आकार 1 लौटना यह सुनिश्चित करता है कि दोनों वस्तुओं का पता एक ही नहीं होगा।


0

यह सुनिश्चित करने के लिए नॉनजरो है कि दो अलग-अलग वस्तुओं के अलग-अलग पते होंगे। विभिन्न वस्तुओं के अलग-अलग पते होने चाहिए, इसलिए एक खाली वर्ग का आकार हमेशा 1 बाइट होता है।


-2

मुझे लगता है कि अगर एक खाली वर्ग का आकार शून्य है, तो इसका मतलब है कि यह मौजूद नहीं है। इसके (वर्ग) मौजूद होने के लिए, इसके लिए कम से कम 1 बाइट होना आवश्यक है, क्योंकि यह बाइट मेमोरी / संदर्भ पता है।


-3

यह इस सूचक की वजह से है , हालांकि सूचक 4 बाइट का (पूर्णांक) है, लेकिन यह एक मेमोरी स्थान (एक यूनिट) को संदर्भित करता है जो 1 बाइट है।


5
क्षमा करें, लेकिन यह बकवास है।
जोगोजपन

@ नारायण दास खत्री: पहला प्रकार का पॉइंटर डेटा प्रकार पर निर्भर करता है जो हमेशा नहीं होता है और दूसरा पॉइंटर का आकार मशीन पर निर्भर करता है और 32 बिट मशीनों पर यह 4 बाइट होता है और 64 बिट मशीनों के लिए यह 8 बाइट होता है।
कृष्ण ओझा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.