2012-01-14 11 views
8

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

#include <iostream> 
using namespace std; 

int main() { 
    cout << "how many elements should the array hold? "; 
    int arraySize; 
    cin >> arraySize; 

    int arr[arraySize]; 

    for (int i = 0; i < arraySize; ++i) 
    arr[i] = i * 2; 

    return 0; 
} 

नोट को इस कार्यक्रम में कोई new या delete ऑपरेटरों देखते हैं कि। यह एक्सकोड 4.2 (डिफ़ॉल्ट क्लैंग कंपाइलर) के साथ-साथ मेरे स्कूल के यूनिक्स सर्वर (जीसीसी 4.4.5) में ठीक काम करता है। कंपाइलर को संकलन समय पर बनाया गया है जब संकलक arr के लिए आवंटित करने के लिए कितनी स्मृति आवंटित करता है? क्या यह सिर्फ मेरे कंपाइलर, खतरनाक कोड का एक झुकाव है जो अन्य स्मृति को दूषित कर सकता है, या यह कानूनी है?

+1

यह एक सुविधा _variable-लंबाई arrays_ कहा जाता है, जो C99 में पहली बार आया उपयोग करता है। –

+3

'g ++ -Wall -Wextra -pedantic -std = C++ 98' –

उत्तर

8

यह आपके सी ++ कंपाइलर्स का एक गैर-मानक विस्तार है। ध्यान दें कि सी में, सी ++ के विपरीत, यह आधिकारिक रूप से समर्थित है (यानी मानक-अनिवार्य व्यवहार) सी 99 के बाद से। सी ++ में, यह समर्थित नहीं है क्योंकि समस्या का समाधान पहले से ही है: सरणी के बजाय std::vector का उपयोग करें।

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

ध्यान दें कि std::vector इसके डेटा को गतिशील स्मृति आवंटन के साथ संग्रहीत करता है। इसी कारण से, आप स्थैतिक std::vector एस के लिए भी एक गैर-स्थिर आकार का उपयोग कर सकते हैं।

+0

मुख्य कारण यह है कि इसकी अनुमति नहीं है कि वेक्टर का विकल्प नहीं है। गहरे कारण हैं, इस तथ्य के रूप में कि एक सरणी का आकार प्रकार का हिस्सा है और इसे संकलन समय पर जाना जाना चाहिए। –

+0

@ डेविडरोड्रिगुएज़-ड्राईबीस: वे उन नियमों के अपवाद बना सकते थे, जैसे सी चर चर लंबाई सरणी के नियमों के अपवादों की आवश्यकता होती है। – celtschk

0

यह Variable Length Array है (केवल सी 99 में समर्थित है और सी ++ में नहीं)। इसे रनटाइम पर ढेर पर आवंटित किया जाता है।

+0

के साथ संकलित करने का प्रयास करें क्या यह वैध C++ भी है? आईआईआरसी विजुअल स्टूडियो के बारे में कुछ त्रुटियां थीं। – stativ

+0

स्टेटिव सही है; यह सी ++ नहीं है। –

+0

नहीं, यह गतिशील स्मृति आवंटन नहीं है। यह स्वचालित स्मृति आवंटन है। @stativ: नहीं, यह मान्य सी ++ नहीं है (यदि सी ++ विशिष्ट कोड से घिरा हुआ नहीं है तो यह वैध सी होगा)। सी ++ के लिए, यह कुछ कंपाइलरों का एक गैर-मानक विस्तार है। – celtschk

1

जेनरेट कोड रनटाइम पर स्टैक पर सरणी आकार बाइट आवंटित करता है। एक बार फ़ंक्शन लौटने के बाद, स्टैक खोलता है, जिसमें सरणी के लिए आवंटित बाइट्स को "वापस देना" शामिल है।

नए और हटाने का उपयोग ढेर पर स्थान आवंटित करने के लिए है। ढेर पर आवंटित स्मृति जीवनकाल किसी भी कार्य या विधि के दायरे से स्वतंत्र होता है - यदि आप किसी फ़ंक्शन में उस पर स्थान आवंटित करते हैं, और फ़ंक्शन लौटाता है, तो स्मृति अभी भी आवंटित और मान्य है।

4

फ़ंक्शन के अंदर घोषित एक सरणी (या कोई ऑब्जेक्ट) के लिए, फ़ंक्शन में प्रविष्टि (आमतौर पर स्टैक पर) पर आवंटित आवंटित किया जाता है और फ़ंक्शन लौटाते समय हटा दिया जाता है। तथ्य यह है कि इस मामले में समारोह main होता है जो इससे प्रभावित नहीं होता है।

यह:

cin >> arraySize; 
int arr[arraySize]; 

एक "चर लंबाई सरणी" है (VLA)। बात यह है कि सी ++ वीएलए का समर्थन नहीं करता है। सी, 1 999 आईएसओ सी मानक (सी 99) से शुरू होता है, लेकिन यह ऐसी सुविधा नहीं है जिसे सी ++ ने अपनाया है।

आपका कंपाइलर एक्सटेंशन के रूप में सी ++ में वीएलए का समर्थन करता है। उनका उपयोग करके आपका कोड गैर पोर्टेबल बनाता है।

(वीएलए के साथ एक समस्या यह है कि आवंटन विफलता का पता लगाने के लिए कोई तंत्र नहीं है; यदि arraySize बहुत बड़ा है, तो प्रोग्राम का व्यवहार अपरिभाषित है)।

जीसीसी के लिए

, -pedantic साथ संकलन एक चेतावनी का उत्पादन करेगा:

warning: ISO C++ forbids variable length array ‘arr’ 
संबंधित मुद्दे