2016-02-15 10 views
6

एक सदिश को देखते हुए, vc, एक के लिए एक सीमा के साथ वेक्टर के माध्यम से पुनरावृति कर सकते हैंक्या वेक्टर पर इटरेटर के बजाए लूप के लिए एक रेंज का उपयोग किया जाना चाहिए?</p> <pre><code>for (auto c : vc) std::cout << c; </code></pre> <p>या पुनरावर्तक के साथ:

for (auto it = vc.cbegin(); it != vc.cend(); ++it) 
    std::cout << *it; 

वहाँ एक दूसरे के ऊपर विधि का उपयोग करने के लिए एक कार्यात्मक कारण है, या यह केवल शैली का मामला है?

+4

ध्यान दें कि श्रेणी-आधारित-लूप में 'ऑटो' के उपयोग के साथ आपको अपने वेक्टर तत्वों की * प्रतिलिपि * मिल रही है, यदि आपकी ऑब्जेक्ट कॉपी करने के लिए महंगी है, तो अवांछित प्रदर्शन समस्याएं उत्पन्न हो सकती हैं। इटरेटर्स के उपयोग के साथ आप एक कॉन्स संदर्भ वापस लेते हैं, इसलिए प्रतियां यहां नहीं होती हैं। रेंज-आधारित में एक कॉन्स संदर्भ वापस पाने का एक तरीका है '(कॉन्स ऑटो और सी: वीसी) ... ' –

उत्तर

4

प्रदर्शन बिंदु से वास्तव में कोई अंतर नहीं है। जैसा कि बजेर्न स्ट्राउस्ट्रप ने अपनी पुस्तक सी ++ प्रोग्रामिंग भाषा में लिखा है चौथा संस्करण:

सबसे सरल लूप एक रेंज-स्टेटमेंट है; यह केवल एक श्रेणी के प्रत्येक तत्व पर प्रोग्रामर पहुंच प्रदान करता है।

केआईएसएस सिद्धांत के प्रशंसक के रूप में मैं अधिक जटिल लोगों पर सरल संरचनाओं को पसंद करता हूं। हालांकि, यह वास्तव में उस चीज़ को उबालता है जिसे आप प्राप्त करना चाहते हैं। उसी पुस्तक से बजेर्ने ने खुलासा किया कि क्यों एक रेंज-फॉर लूप को सरल बनाने के लिए डिज़ाइन किया गया है:

ध्यान दें कि लूप के लिए एक रेंज एक जानबूझकर सरल निर्माण है। उदाहरण के लिए, इसका उपयोग करके आप एक ही समय में दो तत्वों को स्पर्श नहीं कर सकते हैं और एक साथ दो श्रेणियों को प्रभावी रूप से पार नहीं कर सकते हैं। इसके लिए हमें एक सामान्य फॉर-स्टेटमेंट की आवश्यकता है।

इसके परिणामस्वरूप, संदर्भ हैं कि आप रेंज-लूप का उपयोग नहीं कर सकते हैं और आपको क्लासिकल फॉर-स्टेटमेंट में रहना होगा।

लूप लाइन उपयोग सीमा-लूप के लिए जब भी संभव हो क्योंकि सरल और अधिक पठनीय है।

4

यह शैली की बात कम या ज्यादा है, लेकिन इसे इस तरह मानें; रेंज-फॉर लूप स्पष्ट इटरेटर उपयोग से अधिक संक्षिप्त हैं। आपके द्वारा लिखे गए कम कोड, कम जगहें जहां चीजें गलत हो सकती हैं।

+1

इसके अलावा, यह एक बहुत अधिक पठनीय है, क्योंकि यह लूप के कार्यान्वयन विवरण को छुपाता है। – emlai

+1

रेंज के लिए रेंज भी अनुकूलन में सुधार, अनुकूलन में सुधार हो सकता है। – alcedine

+0

अच्छा बिंदु। मैं सहमत हूँ। – JesseTG

2

आपके विशिष्ट उदाहरण के लिए, वे समकक्ष हैं। और चूंकि वे समकक्ष हैं, इसलिए आप स्वाभाविक रूप से सबसे कम संस्करण को प्राथमिकता देना चाहते हैं जो कम से कम त्रुटि-प्रवण होता है - मुफ्त में।

रेंज के लिए पाश भी करने के लिए इसके अलावा छोटा किया जा करने के लिए प्रस्तावित किया गया था:

for (var : range) 

जहां var प्रकार auto&& (उर्फ forwading/सार्वभौमिक संदर्भ) है, जो एक के लिए एक संदर्भ लेने के लिए सबसे अच्छा तरीका है के लिए होता है वस्तु। बस auto var प्रत्येक तत्व की एक प्रति बना देगा, जो सस्ता नहीं हो सकता है। दुर्भाग्य से, यह पास नहीं हुआ।

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

1

आपके दो उदाहरणों के बीच दो महत्वपूर्ण अंतर हैं। सबसे पहले, auto c प्रत्येक तत्व की एक प्रति बनाता है, इसलिए यदि आप अनावश्यक प्रतियां नहीं बनाना चाहते हैं तो auto const& c का उपयोग करें। दूसरा, श्रेणी for गैर-कॉन्स इटरेटर्स के संदर्भ में लागू की गई है, लेकिन आपका for लूप कॉन्स इटरेटर्स का उपयोग करता है।इससे कोई फर्क नहीं पड़ता कि vc एक मानक कंटेनर है, लेकिन कुछ कंटेनर (जैसे कि क्यूटी में) एक आंतरिक साझा सूचक का उपयोग करके कॉपी-ऑन-राइट सेमेन्टिक्स लागू करते हैं, इस मामले में गैर-कॉन्स इटरेटर्स का उपयोग अनावश्यक रूप से पूरे कंटेनर की प्रतिलिपि बनायेगा । आप इस से बच सकते हैं और अभी भी सी ++ 17 std::as_const का उपयोग करके अच्छा रेंज for सिंटैक्स का उपयोग करें:

for (auto const& c : std::as_const(vc)) 
    std::cout << c; 

आप आसानी से as_const के अपने स्वयं के संस्करण को लागू कर सकते हैं यदि आपके वातावरण में यह उपलब्ध नहीं कराता।

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