2016-01-24 26 views
65

पर विचार करें:यह 'लूप' वैध क्यों नहीं है?

int ia[3][4]; 
for (auto row : ia) 
     for (auto col : row) 

पहले for आइए के माध्यम से दोहराता है, जिसका तत्वों आकार के एरे हैं 4. क्योंकि row एक संदर्भ नहीं है, संकलक initializes जब row यह प्रत्येक सरणी तत्व में परिवर्तित कर देंगे (जैसे सरणी प्रकार का कोई अन्य ऑब्जेक्ट) उस सरणी के पहले तत्व के पॉइंटर पर। परिणामस्वरूप, इस लूप में row का प्रकार int* है।

मैं वास्तव में लगता है कि मैं समझता हूँ कि यह कैसे काम करता है ऑटो, लेकिन अगर मैं यह मान सकते हैं यह स्वचालित रूप से एक पंक्ति ia सरणी सदस्यों के आधार पर टाइप करने के लिए एक प्रकार देता है, लेकिन मैं for की क्यों इस तरह की समझ में नहीं आता नहीं कर रहा हूँ , जहां पंक्ति संदर्भ नहीं है, मान्य नहीं है। ऐसा क्यों होने जा रहा है? "उस सरणी के पहले तत्व के सूचक", किस वजह से?

+6

उपयोग कर सकते हैं मैं सी में इस पाया ++ Lippman द्वारा प्राइमर 5 वें संस्करण, पेज 182. –

उत्तर

71

समस्या यह है कि row एक int * और नहीं एक int[4] और वहाँ पता है कि कैसे कई लोगों के लिए तत्वों एक सूचक अंक का कोई स्वचालित मार्ग है, क्योंकि संकेत करने के लिए सरणियों क्षय के रूप में एक उम्मीद होती है।

कि समस्या std::array जोड़ दिया गया है जहां सब कुछ के रूप में की उम्मीद काम करता है चारों ओर पाने के लिए:

#include <array> 

int main() { 
    std::array<std::array<int, 4>, 3> ia; 
    for (auto &row : ia){ 
     for (auto &col : row){ 
      col = 0; 
     } 
    } 
} 

नोट &row और col जो संकेत मिलता है कि आप एक संदर्भ और नहीं पंक्तियों और स्तंभों की प्रतिलिपि बनाना चाहते से पहले, अन्यथा col से 0 को ia पर कोई प्रभाव नहीं पड़ेगा।

+7

+1 को रोकने के लिए ++ 11 विशेषताएं ठीक से। सी ++ केवल पर्यावरण में, इसे संभालने का यह सबसे अच्छा तरीका है। – WeRelic

+49

ध्यान दें कि 'int [3] [4]' के बराबर _not_ 'std :: array , 4>', लेकिन 'std :: array , 3>'। यह एक आम गलती है और मूल्यवान बात है, दोगुनी है क्योंकि आपने इसे भी बनाया है। ; -] – ildjarn

+0

@Deduplicator क्या अस्थायी प्रतियां? – Quentin

38

छोरों ब्रेसिंग, और सी का उपयोग कर के लिए int* को int[] के क्षय आप &&

int main() { 
    int ia[3][4]; 
    for (auto && row : ia) 
     for (auto && col : row) 
      ; 
} 
+8

या सिर्फ सादा संदर्भ पर्याप्त होगा। –

+1

दरअसल, आपको केवल कन्स्ट्रक्टरों में रैवल्यू संदर्भ ('&&') का उपयोग करना चाहिए, असाइनमेंट ऑपरेटरों को ले जाना चाहिए या जब सादे संदर्भ काम नहीं करते हैं और आप वास्तव में जानते हैं कि आप क्या कर रहे हैं। –

+6

मैंने विशेष रूप से '&&' का उपयोग किया क्योंकि [N3853] (http://open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3853] में प्रस्तावित किया जा रहा है।एचटीएम) और भी कम '(elem: संग्रह)' वाक्यविन्यास – Thomas

संबंधित मुद्दे