यह वास्तव में समझाने के लिए एक बहुत कठिन है, लेकिन मैं इसे जाने दूँगा ...
सबसे पहले, dimof
आपको किसी सरणी में आयाम , या तत्वों की संख्या बताता है । (मेरा मानना है कि विंडोज प्रोग्रामिंग वातावरण में "आयाम" पसंदीदा शब्दावली है)।
क्योंकि यह आवश्यक है C++
और C
आप एक सरणी के आकार निर्धारित करने के लिए एक देशी रास्ता देना नहीं है।
अक्सर लोग मानते हैं sizeof(myArray)
कि काम करेगा, लेकिन यह वास्तव में आपको तत्वों की संख्या के बजाय स्मृति में आकार देगा। प्रत्येक तत्व संभवतः 1 बाइट से अधिक मेमोरी लेता है!
अगला, वे कोशिश कर सकते हैं sizeof(myArray) / sizeof(myArray[0])
। यह पहले तत्व के आकार से विभाजित सरणी की स्मृति में आकार देगा। यह ठीक है, और व्यापक रूप से C
कोड में उपयोग किया जाता है । इसके साथ प्रमुख समस्या यह है कि यह काम करने के लिए दिखाई देगा यदि आप एक सरणी के बजाय एक पॉइंटर पास करते हैं। मेमोरी में एक पॉइंटर का आकार आमतौर पर 4 या 8 बाइट्स होगा, भले ही वह जिस बिंदु को इंगित करता है वह तत्वों के अधिकतम का एक सरणी हो सकता है।
तो कोशिश करने के लिए अगली बात यह C++
है कि किसी चीज को बल देने के लिए टेम्प्लेट का उपयोग करें जो केवल सरणियों के लिए काम करता है, और एक पॉइंटर पर एक कंपाइलर त्रुटि देगा। यह इस तरह दिख रहा है:
template <typename T, std::size_t N>
std::size_t ArraySize(T (&inputArray)[N])
{
return N;
}
//...
float x[7];
cout << ArraySize(x); // prints "7"
टेम्पलेट केवल एक सरणी के साथ काम करेगा। यह प्रकार को कम करेगा (वास्तव में आवश्यक नहीं है, लेकिन काम करने के लिए टेम्पलेट प्राप्त करने के लिए होना चाहिए) और सरणी का आकार, फिर यह आकार लौटाता है। जिस तरह से टेम्प्लेट लिखा गया है वह संभवतः एक पॉइंटर के साथ काम नहीं कर सकता है।
आमतौर पर आप यहां रुक सकते हैं, और यह C ++ स्टैंडर्ड लिबरी में है std::size
।
चेतावनी: यहाँ नीचे यह बालों वाली भाषा-वकील क्षेत्र में मिलती है।
यह बहुत अच्छा है, लेकिन अभी भी एक अस्पष्ट धार मामले में विफल रहता है:
struct Placeholder {
static float x[8];
};
template <typename T, int N>
int ArraySize (T (&)[N])
{
return N;
}
int main()
{
return ArraySize(Placeholder::x);
}
ध्यान दें कि सरणी x
है की घोषणा की , लेकिन नहीं परिभाषित । इसके साथ एक फ़ंक्शन (यानी ArraySize
) को कॉल करने के लिए , परिभाषित कियाx
जाना चाहिए ।
In function `main':
SO.cpp:(.text+0x5): undefined reference to `Placeholder::x'
collect2: error: ld returned 1 exit status
आप इसे लिंक नहीं कर सकते।
आपके पास प्रश्न में मौजूद कोड एक तरीका है। वास्तव में किसी फ़ंक्शन को कॉल करने के बजाय, हम एक फ़ंक्शन की घोषणा करते हैं जो बिल्कुल सही आकार का ऑब्जेक्ट देता है । फिर हम sizeof
उस पर ट्रिक का उपयोग करते हैं ।
ऐसा लगता है कि हम फ़ंक्शन को कॉल करते हैं, लेकिन sizeof
विशुद्ध रूप से एक संकलन समय है, इसलिए फ़ंक्शन को वास्तव में कभी नहीं बुलाया जाता है।
template <typename T, size_t N>
char(&DimofSizeHelper(T(&array)[N]))[N];
^^^^ ^ ^^^
// a function that returns a reference to array of N chars - the size of this array in memory will be exactly N bytes
ध्यान दें कि आप वास्तव में किसी फ़ंक्शन से सरणी नहीं लौटा सकते हैं, लेकिन आप किसी सरणी में संदर्भ भेज सकते हैं।
फिर DimofSizeHelper(myArray)
एक अभिव्यक्ति है जिसका प्रकारN
char
एस पर एक सरणी है । अभिव्यक्ति वास्तव में चलने योग्य नहीं है, लेकिन यह संकलन समय पर समझ में आता है।
इसलिए यदि आप वास्तव में फ़ंक्शन को कॉल करते हैं, तो आपको उस समय का आकारsizeof(DimofSizeHelper(myArray))
बताएगा जो आपको मिलेगा। हालांकि हम वास्तव में इसे नहीं कहते हैं।
चिंता मत करो अगर वह आखिरी ब्लॉक कोई मतलब नहीं था। यह एक विचित्र धार मामले के आसपास काम करने के लिए एक विचित्र चाल है। यही कारण है कि आप इस तरह का कोड खुद नहीं लिखते हैं, और लाइब्रेरी के कार्यान्वयनकर्ताओं को इस तरह की बकवास के बारे में चिंता करने दें।
std::array
std::vector