क्या C ++ में सरणियों का उपयोग किया जाना चाहिए?


95

चूंकि std::listऔर std::vectorमौजूद है, इसलिए सी ++ में पारंपरिक सी सरणियों का उपयोग करने का एक कारण है, या क्या उन्हें ऐसे ही टाला जाना चाहिए malloc?



18
@ आल्स: यह प्रश्न दो विशिष्ट कंटेनरों के बीच के अंतर की चिंता करता है, जबकि यह प्रश्न सामान्य रूप से कच्चे सरणियों और मानक कंटेनरों के बीच के अंतर की चिंता करता है।
जॉन पूर्डी

जवाबों:


109

C ++ 11 में जहां std::arrayउपलब्ध है, उत्तर है "हाँ, सरणियों से बचा जाना चाहिए"। C ++ 11 से पहले, आपको स्वचालित भंडारण (यानी स्टैक पर) में सरणियों को आवंटित करने के लिए C सरणियों का उपयोग करने की आवश्यकता हो सकती है।


3
कई कंपाइलरों में अभी भी C ++ 11 सपोर्ट की कमी है। आपको यह तय करना होगा कि जब एक के बजाय एक का उपयोग करना बेहतर होता है तो std की कमी को देखते हुए :: सरणी
Nowayz

4
std :: array एक टेम्प्लेट है, जो T के प्रत्येक संयोजन के लिए बिल्ड समय और संभवतः कोड आकार के संदर्भ में बड़ी परियोजनाओं को प्रभावित करता है, एन टेम्पलेट तात्कालिक रूप से नए सिरे से बनाया गया है।
ज़वरा

std :: वेक्टर मानक द्वारा डेटा संरेखण की गारंटी देता है, इसलिए इसका उपयोग लगभग हर जगह किया जा सकता है। C ++ 11 के साथ वास्तव में C सरणियों का उपयोग करने का कोई कारण नहीं है।
निल्स

16
@ नील सरणियाँ भी संरेखण की गारंटी देती हैं। इसके अलावा, स्वचालित भंडारण आवंटन ("स्टैक") गतिशील भंडारण आवंटन की तुलना में तेज़ है। अगर मुझे पता है कि मेरे पास बिल्कुल 3 तत्व हैं [उदाहरण के लिए, एक त्रिकोण के निर्देशांक], तो वेक्टर का उपयोग करने का कोई कारण नहीं है।
ज़वरा

9
@zvrba - std का उपयोग करते समय उत्पन्न विधानसभा की जाँच करें :: सरणी बनाम C सरणियाँ। कोई अंतर नहीं।
निमन्जा ट्रिफ़ुनोविक

85

निश्चित रूप से, हालांकि std::arrayC ++ 11 में, व्यावहारिक रूप से केवल स्थैतिक डेटा के लिए। C शैली सरणियों के तीन महत्वपूर्ण फायदे हैं std::vector:

  • उन्हें गतिशील आवंटन की आवश्यकता नहीं है। इस कारण से, C शैली सरणियों को प्राथमिकता दी जानी चाहिए, जहां आपको बहुत छोटे सरणियों की संभावना हो। एक n- आयाम बिंदु की तरह कुछ कहें:

    template <typename T, int dims>
    class Point
    {
        T myData[dims];
    // ...
    };

    आमतौर पर, कोई कल्पना कर सकता है कि dimsबहुत छोटा (2 या 3), Tएक बिल्ट-इन टाइप ( double) होगा, और आप std::vector<Point>लाखों तत्वों के साथ समाप्त हो सकते हैं। आप निश्चित रूप से 3 डबल के लाखों गतिशील आवंटन नहीं चाहते हैं।

  • समर्थन स्थैतिक प्रारंभ। यह केवल स्थैतिक डेटा के लिए एक मुद्दा है, जहां कुछ इस तरह है:

    struct Data { int i; char const* s; };
    Data const ourData[] =
    {
        { 1, "one" },
        { 2, "two" },
        //  ...
    };

    यह अक्सर वेक्टर (और std::string) का उपयोग करने के लिए बेहतर होता है , क्योंकि यह आरंभीकरण के मुद्दों के सभी क्रम से बचा जाता है ; किसी भी वास्तविक कोड को निष्पादित करने से पहले डेटा को पहले से लोड किया जाता है।

  • अंत में, ऊपर से संबंधित, कंपाइलर इनिशियलाइज़र से सरणी के वास्तविक आकार की गणना कर सकता है। आपको उन्हें गिनने की जरूरत नहीं है।

यदि आपके पास C ++ 11 तक पहुंच है, std::arrayतो पहले दो मुद्दों को हल करता है, और निश्चित रूप से पहले मामले में C शैली सरणियों के लिए प्राथमिकता में उपयोग किया जाना चाहिए। हालांकि, यह तीसरे को संबोधित नहीं करता है, और संकलक की संख्या के अनुसार सरणी आयाम होने के बावजूद अभी भी सी शैली सरणियों को पसंद करने का एक वैध कारण है।


11
सी-स्टाइल सरणी आरंभीकरण भी खुद को दोहराने की आवश्यकता को हटा देता है। int i[] = { 1, 2, 3 };के साथ काम करना जारी रखता है int i[] = { 1, 2, 3, 4 };array<int, 3>मैन्युअल रूप से परिवर्तित करने की आवश्यकता है array<int, 4>

10
@JoeWreschnig एक बदलाव जिसे आप आसानी से भूल सकते हैं। यदि आप एक तत्व जोड़ते हैं, तो संकलक को शिकायत करनी चाहिए, लेकिन यदि आप एक को हटाते हैं, तो आप अंत में एक अतिरिक्त, 0 प्रारंभिक तत्व के साथ समाप्त हो जाएंगे। मैं अभी भी स्थैतिक डेटा के इस प्रकार के लिए बड़े पैमाने पर सी शैली सरणियों का उपयोग करता हूं।
जेम्स कंज

3
पहला वाक्य समझ में नहीं आता है।
कोनराड रुडोल्फ

4
तीसरे बिंदु को हल किया जा सकता है, बल्कि किसी make_arrayफ़ंक्शन का उपयोग करके , make_pairआदि जैसे हैट-टिप से @R तक। मार्टिनो फर्नांडीस
कोनराड रुडोल्फ

@KonradRudolph: निश्चित रूप से यह करता है। एंड्रियास पूछता है कि "सी + + में सरणियों का उपयोग किया जाना चाहिए?", जिसमें जेम्स उत्तर देता है "निश्चित रूप से, हालांकि std::arrayसी ++ 11 में, [उनका उपयोग किया जाना चाहिए] व्यावहारिक रूप से केवल स्थैतिक डेटा के लिए"।
जॉन पुरडी

15

कभी भी "कभी नहीं" कहें, लेकिन मैं सहमत हूं कि एसटीएल से सही डेटा संरचनाओं द्वारा उनकी भूमिका बहुत कम है।

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


11

मैंने सुरक्षा महत्वपूर्ण प्रणालियों पर काम किया है जहाँ आप गतिशील मेमोरी आवंटन का उपयोग करने में असमर्थ हैं। मेमोरी हमेशा स्टैक पर होनी चाहिए। इसलिए इस मामले में आप सरणियों का उपयोग करेंगे क्योंकि आकार संकलन समय पर तय किया गया है।


8
C ++ 11 से पहले मैं सहमत था, लेकिन std::array<T>स्टैक पर आवंटित करता है और मूल रूप से कच्चे सरणी पर कोई ओवरहेड नहीं होता है।
111111

5
@ 111111 - सहमत। लेकिन मुझे पता है कि उस उद्योग के कुछ लोग अभी तक C ++ 11 में नहीं गए हैं
Ed Heal

मुझे पता है यही कारण है कि मैंने आपको निराश नहीं किया, लेकिन मुझे लगता है कि बढ़ावा देने के लिए एक संस्करण था और साथ ही अपने खुद के रोल करना आसान है।
111111

6
लेकिन सुरक्षा महत्वपूर्ण प्रणालियों में, आप नई संकलक सुविधाओं (कम परीक्षण) का उपयोग नहीं करते हैं, और आप बूस्ट का उपयोग नहीं करते हैं।
जेम्स कांजे

3
कई सुरक्षा महत्वपूर्ण प्रणालियां OLD कंपाइलरों पर बनाई गई हैं, जिनमें नए कंपाइलर फीचर्स भी नहीं हैं क्योंकि टूलचिन्स बदलना एक धीमी, महंगी प्रक्रिया है जिसके लिए कागजी कार्रवाई, परीक्षण और प्रमाणपत्र की आवश्यकता होती है।
ब्रायन मैकफारलैंड

6

arrayमें c++देता है आप आकार गतिशील के तेजी से विकल्प तय आकार std::vectorऔर std::liststd :: array , परिवर्धन में से एक है c++11। यह सी-स्टाइल सरणियों के कुल प्रकार के शब्दार्थ प्रदान करते हुए एसटीडी कंटेनरों का लाभ प्रदान करता है।

तो c++11मैं निश्चित रूप से उपयोग करेंगे std::array, जहां यह आवश्यक है, वेक्टर पर। लेकिन मैं सी शैली सरणी से बचना चाहता हूँ C++03


4

आम तौर पर, नहीं , मैं कच्चे सरणियों का उपयोग करने के लिए एक कारण के बारे में नहीं सोच सकता, कहते हैं vectors,। अगर कोड नया है

यदि आपके लाइब्रेरीज़ को कोड और कच्चे पॉइंटर्स की अपेक्षा करते हैं, तो आपको सरणियों का उपयोग करने का सहारा लेना पड़ सकता है।


1
... लेकिन चूंकि सी ++ 03 एक वेक्टर "वास्तव में" एक सरणी है, जिसे आप पढ़ने या लिखने के लिए पॉइंटर द्वारा पहुंच सकते हैं। ताकि कोड के अधिकांश मामलों को कवर किया जा सके, जो इंगित करता है कि सरणियों को इंगित करता है। यह वास्तव में केवल तभी होता है जब वह कोड उस सरणी को आवंटित या मुक्त करता है जिसे आप वेक्टर का उपयोग नहीं कर सकते हैं।
स्टीव जेसोप

@SteveJessop आप आंतरिक सरणी तक पहुँच सकते हैं?
लुचियन ग्रिगोर

1
@LuchianGrigore: vector.data()C ++ 11 में या &vector.front()पहले।
माइक सेमोर

@ ल्यूचियन: बशर्ते वेक्टर खाली न हो, आप एक पॉइंटर को एक तत्व में ले जा सकते हैं (और अगर यह खाली है, तो आप किसी भी समझदारी से लिखे गए फ़ंक्शन को शून्य पॉइंटर और 0 की लंबाई पास कर सकते हैं जो ए के किनारे के मामले को स्वीकार करता है। शून्य आकार के बफर)। C ++ 03 में जोड़ी गई वेक्टर संदर्भ गारंटी का बहुत ही एकमात्र उद्देश्य वैक्टर को सूचक-उन्मुख कोड द्वारा बफ़र्स के रूप में उपयोग करने की अनुमति देना था।
स्टीव जेसोप

1
@SteveJessop और यह तथ्य कि बहुत सारे लोगों ने सोचा कि यह वैसे भी गारंटी है, और उन्हें निराश नहीं करना बेहतर माना जाता था।
जेम्स कांजे

4

मुझे पता है कि बहुत से लोग स्टैक पर सरणी को आवंटित करने के लिए std :: array को इंगित कर रहे हैं और ढेर :: वेक्टर ढेर के लिए। लेकिन न तो गैर-देशी संरेखण का समर्थन करते हैं। यदि आप किसी भी प्रकार के संख्यात्मक कोड का उपयोग कर रहे हैं, तो आप SSE या VPX निर्देशों का उपयोग करना चाहते हैं (इस प्रकार क्रमशः 128 या 256 बाइट संरेखण की आवश्यकता होती है), C सरणियाँ अभी भी आपकी सबसे अच्छी शर्त होगी।


3

मैं कहूंगा कि सरणियाँ अभी भी उपयोगी हैं, यदि आप डेटा की एक छोटी स्थिर राशि का भंडारण कर रहे हैं तो क्यों नहीं।


2

एक सरणी का एकमात्र लाभ (निश्चित रूप से किसी चीज़ में लिपटा हुआ, जो ज़रूरत पड़ने पर स्वचालित रूप से अपने सौदे का प्रबंधन करेगा) के std::vectorबारे में मैं सोच सकता हूं कि vectorयह अपने डेटा के स्वामित्व को पारित नहीं कर सकता है, जब तक कि आपका कंपाइलर सी ++ 11 का समर्थन नहीं करता है और निर्माणकर्ताओं को स्थानांतरित नहीं करता है।


6
"वेक्टर अपने डेटा के स्वामित्व को पारित नहीं कर सकता है" - हां, यह C ++ 03 में, उपयोग कर सकता है swap
स्टीव जेसोप

2

सी शैली सरणियां एक मौलिक डेटा संरचना हैं, इसलिए ऐसे मामले होंगे जब इसका उपयोग करना बेहतर होगा। हालाँकि, सामान्य स्थिति के लिए, अधिक उन्नत डेटा संरचनाओं का उपयोग करें जो अंतर्निहित डेटा के कोनों को बंद करते हैं। सी ++ आपको मेमोरी के साथ कुछ बहुत ही रोचक और उपयोगी चीजें करने की अनुमति देता है, जिनमें से कई सरल सरणियों के साथ काम करते हैं।


3
C- शैली सरणियाँ std::arrays से अधिक मौलिक कैसे हैं ? दोनों कई मामलों में एक ही विधानसभा में संकलित किए जाएंगे।
12:30

1
इसमें जो मौलिक है, वह ज्यादा बुनियादी है। आप जानते हैं कि एक सरणी क्या करने जा रही है, std :: सरणी में कार्यान्वयन क्वैर हो सकता है क्योंकि यह मानक पुस्तकालय पर निर्भर करता है।
जेम्स व्यान

1
@JamesWynn वास्तव में नहीं। std::arrayस्थैतिक सरणियों के शीर्ष पर बनाया गया ठीक परिभाषित शब्दार्थ है।
कोनराड रुडोल्फ

1

आपको आंतरिक रूप से एसटीएल कंटेनरों का उपयोग करना चाहिए, लेकिन आपको अलग-अलग मॉड्यूल के बीच ऐसे कंटेनरों को पॉइंटर्स पास नहीं करना चाहिए, या आप निर्भरता नरक में समाप्त हो जाएंगे। उदाहरण:

std::string foo;
//  fill foo with stuff
myExternalOutputProc(foo.c_str());

एक बहुत अच्छा समाधान है, लेकिन नहीं

std::string foo;
//  fill foo with stuff
myExternalOutputProc(&foo);

कारण यह है कि std :: string को कई अलग-अलग तरीकों से लागू किया जा सकता है लेकिन एक c-style string हमेशा एक c-style string है।


मुझे लगता है कि आप जो कहना चाह रहे हैं, वह है: विभिन्न ऑब्जेक्ट कोड को एक साथ लिंक न करें यदि उन्हें बनाने के लिए मानक लाइब्रेरी के विभिन्न कंपाइलरों / कार्यान्वयन का उपयोग किया गया था। यह निश्चित रूप से सच है। यह मूल प्रश्न से कैसे संबंधित है?
जोगोजपन

यह केवल एक सलाह है जब सरणियों या एसटीएल कंटेनरों का उपयोग करना चाहिए। एक कंटेनर का उपयोग करके डेटा बनाएं, इसे एक सरणी के रूप में पास करें। अन्य डेटा के लिए जो आपको तार देता है जैसे कि myExternalOutputProc (foo.rawPointerGet (), foo.count ());
user877329

लेकिन ये समस्याएँ तब उत्पन्न होती हैं जब आप एक ही परियोजना में मानक पुस्तकालय के विभिन्न कार्यान्वयनों को जोड़ते हैं। वह पागल है। कोड के किसी भी सामान्य टुकड़े में, किसी फ़ंक्शन को पास करना, कहना, एक वेक्टर, संदर्भ द्वारा (या, C ++ 11 में, इसे स्थानांतरित करना) पूरी तरह से ठीक है।
जोगोजपन

1
मैं सिर्फ प्लग-इन को पसंद करता
हूं
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.