अब जब हमारे पास std :: सरणी है तो C- शैली सरणियों के लिए कौन से उपयोग शेष हैं?


88

std::arrayसी सरणियों से काफी बेहतर है। और यहां तक ​​कि अगर मैं विरासत कोड के साथ हस्तक्षेप करना चाहता हूं, तो मैं सिर्फ उपयोग कर सकता हूं std::array::data()। क्या कोई कारण है कि मैं कभी भी एक पुराने स्कूल की सरणी चाहता हूँ?

जवाबों:


60

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

MyStruct const table[] =
{
    { something1, otherthing1 },
    //  ...
};

उन पर पुनरावृति करने के लिए सामान्य beginऔर endटेम्पलेट फ़ंक्शंस (C ++ 11 में अपनाया गया) का उपयोग करना। कभी भी आकार का उल्लेख किए बिना, जो संकलक शुरुआती की संख्या से निर्धारित करता है।

संपादित करें: एक और बात मैं भूल गया: स्ट्रिंग शाब्दिक अभी भी सी शैली सरणियाँ हैं; प्रकार के साथ char[]। मुझे नहीं लगता कि किसी को भी स्ट्रिंग शाब्दिक का उपयोग करने से बाहर रखा जाएगा क्योंकि हमारे पास है std::array


7
आप एक वैरेडिक फ़ंक्शन टेम्प्लेट लिख सकते हैं जो लंबाई निर्दिष्ट करने के लिए आपके बिना सरणियों का निर्माण करता है।
राइटफोल्ड

2
C ++ 17 क्लास टेम्पलेट डिडक्शन के साथ शुरुआती लोगों की संख्या में स्वत: कटौती का समर्थन किया जाता है। उदाहरण के लिए, "auto a = std :: array {1, 2, 3};"
रिकी 65

नाइटपिक: स्ट्रिंग शाब्दिक का प्रकार हैconst char[]
बुलेट्मैग्नेट

30

नहीं, उह, इसे स्पष्ट रूप से रखें। और 30 अक्षरों में।

बेशक, आपको लागू करने के लिए सी सरणियों की आवश्यकता है std::array, लेकिन यह वास्तव में एक कारण नहीं है कि कोई उपयोगकर्ता कभी भी सी सरणियां चाहता है। इसके अलावा, नहीं, std::arrayसी सरणी से कम परफॉर्मेंट नहीं है, और इसमें बाउंड-चेक एक्सेस का विकल्प है। और अंत में, यह किसी भी C ++ प्रोग्राम के लिए पूरी तरह से उचित है कि वह मानक पुस्तकालय पर निर्भर हो- यह उस तरह का बिंदु है जो मानक है- और यदि आपके पास मानक पुस्तकालय तक पहुंच नहीं है, तो आपका संकलक गैर-अनुरूप है और प्रश्न "C ++" को टैग किया गया है, न कि "C ++ और उन नहीं-C ++ चीजों को जो आधे विनिर्देश को याद करते हैं क्योंकि यह अनुचित लगा।"


1
हम्म। क्या होगा यदि आप C ++ कोड लिख रहे हैं जो किसी अन्य भाषा से कॉल किया जाता है और पैरामीटर के रूप में पारित होने के लिए कुछ की आवश्यकता होती है?
asveikau

3
फ्रीस्टैंडिंग कार्यान्वयन को लगभग सभी मानक पुस्तकालय से बाहर जाने की अनुमति है और अभी भी अनुपालन है। मुझे एक संकलक के बारे में गंभीर संदेह होगा जो std::arrayएक फ्रीस्टैंडिंग सी ++ 11 कार्यान्वयन में लागू नहीं कर सकता था , हालांकि।
डेनिस ज़िकफ़ोज

11
C ++ 0x अंतिम ड्राफ्ट (दस्तावेज़ N3092) "1.4.7" कार्यान्वयन के दो प्रकार परिभाषित किए गए हैं: होस्ट किए गए और फ्रीस्टैंडिंग। एक होस्ट किए गए कार्यान्वयन के लिए, यह अंतर्राष्ट्रीय मानक उपलब्ध पुस्तकालयों के सेट को परिभाषित करता है। एक फ्रीस्टैंडिंग कार्यान्वयन एक है जिसमें निष्पादन हो सकता है। एक ऑपरेटिंग सिस्टम के लाभ के बिना जगह ले लो, और पुस्तकालयों के कार्यान्वयन-परिभाषित सेट है जिसमें कुछ भाषा-समर्थन पुस्तकालय शामिल हैं ".. एसटीएल एक फ्रीस्टैंडिंग कंपाइलर में" भाषा-समर्थन "पुस्तकालय के रूप में शामिल नहीं है
अर्लज़

24

लगता है जैसे बहुआयामी सरणियों का उपयोग सी सरणियों से आसान है std::array। उदाहरण के लिए,

char c_arr[5][6][7];

विरोध के रूप में

std::array<std::array<std::array<char, 7>, 6>, 5> cpp_arr;

इसके अलावा, सी सरणियों की स्वचालित क्षय संपत्ति के कारण, c_arr[i]ऊपर के उदाहरण में एक सूचक को क्षय हो जाएगा और आपको बस शेष आयामों को दो और मापदंडों के रूप में पारित करने की आवश्यकता है। मेरी बात यह c_arrहै कि नकल करना महंगा नहीं है। हालाँकि, cpp_arr[i]कॉपी करना बहुत महंगा पड़ेगा।


1
हालाँकि, आप arrayआयामों को खोए बिना एक फ़ंक्शन के लिए बहुआयामी पास कर सकते हैं । और यदि आप इसे एक फंक्शन टेम्प्लेट में पास करते हैं, तो वह फंक्शन दोनों आयाम और प्रत्येक आयाम के आकार को घटा सकता है, या उन दोनों में से एक को भी। यह वैज्ञानिक टेम्पलेट पुस्तकालयों के लिए दिलचस्प हो सकता है जो मुख्य रूप से मनमाने आयामों पर काम करते हैं।
सेबस्टियन मच

29
एक साधारण template <typename T, int M, int N> using array2d = std::array<std::array<T, N>, M>;को उन मुद्दों में से किसी को हल करना चाहिए।
माइल्स राउत

6
आपका उदाहरण c_arrहै बहुत कॉपी करने के लिए महंगा! आपको ऐसा करने के लिए कोड प्रदान करना होगा। सूचक जो इसे क्षय करेगा वह प्रतिलिपि की तुलना में संदर्भ के समीप है और std::arrayयदि आप चाहते हैं तो संदर्भ को पास करने के लिए उपयोग कर सकते हैं।
चेतस

1
@ मीलों तकनीकी रूप से , std::size_tइसके बजाय ऐसा नहीं होना चाहिए int? नाइटपैकिंग के लिए खेद है, लेकिन यह इसे सार्वभौमिक बना देगा।
रॉबी

1
@ robbie0630 हाँ, आप चाहें तो इसे बना सकते size_tहैं, हालाँकि मैं सोच भी नहीं सकता कि ऐसे कई परिदृश्य हैं जहाँ 4 बिलियन से अधिक पंक्तियों या स्तंभों के साथ सरणियाँ आवश्यक हैं।
माइल्स राउत

13

जैसा कि सुमंत ने कहा, बहु-आयामी सरणियों के साथ-साथ सी-सरणियों में निर्मित उपयोग करने के लिए बहुत आसान है std::array

जब नेस्ट किया जाता है, तो std::arrayपढ़ना और अनावश्यक रूप से क्रिया करना बहुत कठिन हो सकता है।

उदाहरण के लिए:

std::array<std::array<int, 3>, 3> arr1; 

की तुलना में

char c_arr[3][3]; 

यह भी ध्यान दें begin(), end()और size()जब आप घोंसला बनाते हैं , तो सभी व्यर्थ मान लौटाते हैं std::array

इन कारणों से मैंने अपना निश्चित आकार का बहुआयामी सरणी कंटेनर बनाया है, array_2dऔर array_3d। वे अनुरूप हैं, std::arrayलेकिन 2 और 3 आयामों के बहुआयामी सरणियों के लिए। वे सुरक्षित हैं और अंतर्निहित बहुआयामी सरणियों की तुलना में कोई बुरा प्रदर्शन नहीं है। मैंने 3 से अधिक आयाम वाले बहु-आयामी सरणियों के लिए एक कंटेनर को शामिल नहीं किया क्योंकि वे असामान्य हैं। C ++ 0x में एक वैरैडिक टेम्प्लेट संस्करण बनाया जा सकता है जो एक मनमाना संख्या में आयामों का समर्थन करता है।

द्वि-आयामी संस्करण का एक उदाहरण:

//Create an array 3 x 5 (Notice the extra pair of braces) 

fsma::array_2d <double, 3, 5> my2darr = {{
    { 32.19, 47.29, 31.99, 19.11, 11.19},
    { 11.29, 22.49, 33.47, 17.29, 5.01 },
    { 41.97, 22.09, 9.76, 22.55, 6.22 }
}};

पूर्ण प्रलेखन यहाँ उपलब्ध है:

http://fsma.googlecode.com/files/fsma.html

आप यहाँ पुस्तकालय डाउनलोड कर सकते हैं:

http://fsma.googlecode.com/files/fsma.zip


4
फिक्स्ड-साइज़ C-style सरणियाँ आसान हैं, लेकिन यदि आप भिन्न करना चाहते हैं तो आयाम जटिल हो जाते हैं। उदाहरण के लिए, दिया गया arr[x][y], आप यह नहीं बता सकते हैं कि arrएरे की एक सरणी, पॉइंटर्स की एक सरणी, एक सरणी के लिए एक पॉइंटर, या पॉइंटर को एक पॉइंटर है; कार्यान्वयन के लिए सभी आपकी आवश्यकताओं के आधार पर वैध हैं। और शायद बहु-आयामी सरणियों के लिए सबसे वास्तविक दुनिया के उपयोग के मामलों को रन समय पर निर्धारित करने की आवश्यकता होती है।
कीथ थॉम्पसन

मुझे n-आयामी सरणियों के उस वैरिएड-टेम्प्लेट-कार्यान्वयन को देखना अच्छा लगेगा! मेटा-प्रोग्रामिंग अपने सबसे अच्छे रूप में!
स्टीफन

3
@ जल्द ही मैंने कुछ साल पहले एक प्रयास किया था। आप इसे यहाँ देख सकते हैं: code.google.com/p/fsma/source/browse/trunk/… । यहां टेस्ट मामला: code.google.com/p/fsma/source/browse/trunk/... । मुझे यकीन है कि यह एक बहुत अच्छा किया जा सकता है, हालांकि।
15:65 बजे रिकी 65

5

C ++ में उपलब्ध C- शैली सरणियाँ वास्तव में वास्तविक C- सरणियों की तुलना में बहुत कम बहुमुखी हैं। अंतर यह है कि, सी में, सरणी प्रकारों में रनटाइम आकार हो सकते हैं । निम्नलिखित सी कोड मान्य है, लेकिन इसे न तो C ++ C- शैली सरणियों के साथ व्यक्त किया जा सकता है और न ही C ++ array<>प्रकारों के साथ:

void foo(int bar) {
    double tempArray[bar];
    //Do something with the bar elements in tempArray.
}

C ++ में, आपको ढेर पर अस्थायी सरणी आवंटित करनी होगी:

void foo(int bar) {
    double* tempArray = new double[bar];
    //Do something with the bar elements behind tempArray.
    delete[] tempArray;
}

इसे प्राप्त नहीं किया जा सकता है std::array<>, क्योंकि barसंकलन समय पर ज्ञात नहीं है, इसके लिए C ++ में या तो C- शैली सरणियों के उपयोग की आवश्यकता होती है std::vector<>


हालांकि पहला उदाहरण अपेक्षाकृत आसानी से C ++ में व्यक्त किया जा सकता है (यद्यपि आवश्यकता होती है new[]और delete[]), निम्नलिखित बिना C ++ में प्राप्त नहीं किया जा सकता है std::vector<>:

void smoothImage(int width, int height, int (*pixels)[width]) {
    int (*copy)[width] = malloc(height*sizeof(*copy));
    memcpy(copy, pixels, height*sizeof(*copy));
    for(y = height; y--; ) {
        for(x = width; x--; ) {
            pixels[y][x] = //compute smoothed value based on data around copy[y][x]
        }
    }
    free(copy);
}

मुद्दा यह है कि, लाइन सरणियों के संकेत int (*)[width]C ++ में रनटाइम चौड़ाई का उपयोग नहीं कर सकते हैं, जो सी + + में किसी भी छवि हेरफेर कोड को बहुत अधिक जटिल बनाता है। यह सी में एक विशिष्ट सी + + है। छवि हेरफेर उदाहरण का एक विशिष्ट सी ++ कार्यान्वयन इस तरह दिखेगा:

void smoothImage(int width, int height, int* pixels) {
    int* copy = new int[height*width];
    memcpy(copy, pixels, height*width*sizeof(*copy));
    for(y = height; y--; ) {
        for(x = width; x--; ) {
            pixels[y*width + x] = //compute smoothed value based on data around copy[y*width + x]
        }
    }
    delete[] copy;
}

यह कोड ठीक उसी तरह की गणना करता है जैसा कि ऊपर C कोड है, लेकिन इसे इंडेक्स कम्प्यूटेशन को हाथ से करने की आवश्यकता है जहां सूचकांक का उपयोग किया जाता है । 2 डी मामले के लिए, यह अभी भी संभव है (भले ही यह सूचकांक गणना को गलत करने के लिए बहुत सारे अवसरों के साथ आता है)। यह 3 डी मामले में वास्तव में बुरा हो जाता है, हालांकि।

मुझे C ++ में कोड लिखना पसंद है। लेकिन जब भी मुझे बहुआयामी डेटा में हेरफेर करने की आवश्यकता होती है, तो मैं वास्तव में खुद से पूछता हूं कि क्या मुझे कोड के उस हिस्से को सी में स्थानांतरित करना चाहिए।


7
यह ध्यान दिया जाना चाहिए कि कम से कम क्लैंग और जीसीसी सी ++ में वीएलए का समर्थन करते हैं।
जानूस ट्रॉल्सन

@JanusTroelsen और यह भी कि वे बुरी तरह से सीमित हैं कि वे किस प्रकार के तत्वों का समर्थन करते हैं।
राइटफोल्ड

क्या C11 VLA को वैकल्पिक नहीं बनाता है? अगर ऐसा है तो मुझे लगता है कि आपका जवाब भ्रामक है। यह सही होगा जब C99 मानक था लेकिन C11 नहीं।
जेड बोसोन

1
@Zboson C99 एक C मानक है, और ऐसे कंपाइलर हैं जो इसकी VLA सुविधाओं ( gccउदाहरण के लिए) को लागू करते हैं। C11 ने काफी दिलचस्प सामान को वैकल्पिक बना दिया है, और मुझे नहीं लगता कि ऐसा इसलिए है क्योंकि वे इस सुविधा को रेखांकित करना चाहते हैं। मैं इसे एक संकेत के रूप में देखता हूं कि वे पूरी तरह से मानक अनुरूप संकलक लिखने के लिए स्तर कम करना चाहते थे: वीएलए को लागू करने के लिए काफी कठिन जानवर हैं, और बहुत से कोड बिना कर सकते हैं, इसलिए यह नए संकलक के लिए नया अर्थ देता है वीएलए के अधिकार को अभी लागू नहीं करना है।
विस्फ़ोटक -

-1

हो सकता है std::arrayकि यह धीमा न हो। लेकिन मैंने साधारण स्टोर का उपयोग करके कुछ बेंचमार्किंग की और एसटीडी :: सरणी से पढ़ा; नीचे दिए गए बेंचमार्क परिणाम देखें (W8.1, VS2013 अपडेट 4 पर):

ARR_SIZE: 100 * 1000
Avrg = Tick / ARR_SIZE;

test_arr_without_init
==>VMem: 5.15Mb
==>PMem: 8.94Mb
==>Tick: 3132
==>Avrg: 0.03132
test_arr_with_init_array_at
==>VMem: 5.16Mb
==>PMem: 8.98Mb
==>Tick: 925
==>Avrg: 0.00925
test_arr_with_array_at
==>VMem: 5.16Mb
==>PMem: 8.97Mb
==>Tick: 769
==>Avrg: 0.00769
test_c_arr_without_init
==>VMem: 5.16Mb
==>PMem: 8.94Mb
==>Tick: 358
==>Avrg: 0.00358
test_c_arr_with_init
==>VMem: 5.16Mb
==>PMem: 8.94Mb
==>Tick: 305
==>Avrg: 0.00305

नकारात्मक चिह्नों के अनुसार, मैंने जो कोड इस्तेमाल किया है वह पास्टबिन ( लिंक ) में है

बेंचमार्क क्लास कोड यहाँ है ;

मैं बेंचमार्किंग के बारे में बहुत कुछ नहीं जानता ... मेरा कोड त्रुटिपूर्ण हो सकता है


6
बेंचमार्क कोड, या संकलन झंडे के बिना बेंचमार्क परिणाम? चलो, तुम बेहतर कर सकते हो।
आर। मार्टिनो फर्नांडीस

एफडब्ल्यूआईडब्ल्यू, कोड के छोटे बिट पहले से ही दिखाता है कि बेंचमार्क गंभीर रूप से त्रुटिपूर्ण है। एक स्मार्ट पर्याप्त संकलक पूरी चीज़ को बस में बदल देगाlong test_arr_without_init() { return ARR_SIZE; }
आर। मार्टिनो फर्नांडीस

वह सिर्फ एक उदाहरण था। मुझे लगा कि यह कोई बड़ी बात नहीं है। मैंने वीओएस 2013 में रिलीज़ बिल्ड का उपयोग करने के लिए / O2 / Ot / Gl के साथ शून्य का उपयोग करते हुए कोड को बदल दिया।
K'Prime 13

रिटर्न वैल्यू को हटाने का मतलब है कि कंपाइलर पूरी चीज़ को चालू कर सकता है void test_arr_without_init() {}। आपको वास्तव में हुप्स के माध्यम से कूदने की ज़रूरत है यह सुनिश्चित करने के लिए कि आप जिस कोड को माप रहे हैं वह कोड है जिसे आप मापना चाहते हैं।
आर। मार्टिनो फर्नांडिस

-6
  1. जैसे कुछ लागू करने के लिए std::array
  2. यदि आप एसटीएल का उपयोग नहीं करना चाहते हैं या नहीं कर सकते हैं
  3. प्रदर्शन के लिए

27
मुझे बताओ कि std::arrayC सरणी से कम प्रदर्शन कैसा रहेगा।
Xeo

2
विकिपीडिया से : "सरणी कार्यान्वयन के लिए बाध्य चेक करने की आवश्यकता नहीं है। हालांकि, कार्यान्वयन में कार्यान्वयन ऑपरेटर [] के लिए होता है, लेकिन पुनरावृत्तियों के लिए नहीं।" - इसलिए ऑपरेटर [] धीमा है। मैंने कार्यान्वयन पर ध्यान नहीं दिया है, लेकिन कार्यान्वयन में कोई भी कोड अनुकूलक के रास्ते में आ सकता है।
लू फ्रैंको

19
@ एरॉन मैकडैड: यह केवल में है at(), यह अंदर की operator[]तरह नहीं है std::vector। कोई प्रदर्शन में कमी या कोड ब्लोट नहीं है std::array, कंपाइलर को इस तरह की चीज़ को अनुकूलित करने के लिए डिज़ाइन किया गया है। और, ज़ाहिर है, चेक किए गए फ़ंक्शन का जोड़ एक उत्कृष्ट डिबग टूल और एक बड़ा लाभ है। @Lou फ्रेंको: सभी C ++ कोड मानक पुस्तकालय पर निर्भर हो सकते हैं- यह इस तरह का है। @ एर्लज़: यदि आपके पास एसटीएल उपलब्ध नहीं है, तो यह सी ++ नहीं है, और यह उसी का अंत है।
पिल्ला

6
@ एर्लज़: सी ++ मानक में मानक पुस्तकालय शामिल है। यदि आप पुस्तकालय का उपयोग नहीं कर सकते हैं, तो यह अनुरूप नहीं है। और दूसरी बात, आपके पास std::arrayबराबर सी सरणी उपयोग की तुलना में बड़ा होने के लिए एक शाइनी कंपाइलर का एक नरक होना चाहिए ।
पिल्ला

5
@ एर्लज़: "काफी अनुरूप नहीं" और "गायब विशेषताओं के बीच एक बड़ा अंतर है जो विनिर्देश में सैकड़ों पृष्ठ हैं"।
पिल्ला
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.