2012-10-29 11 views
77

const auto& पर्याप्त होगा यदि मैं केवल-पढ़ने के लिए संचालन करना चाहता हूं। हालांकि, मैंनेलूप के लिए श्रेणी-आधारित में सार्वभौमिक संदर्भों का उपयोग करने का क्या फायदा है?

for (auto&& e : v) // v is non-const 

हाल ही में कुछ बार बंप किया है। इससे मुझे आश्चर्य होता है:

क्या यह संभव है कि कुछ अस्पष्ट कोनों के मामलों में auto& या const auto& की तुलना में सार्वभौमिक संदर्भों का उपयोग करने में कुछ प्रदर्शन लाभ है?

Any disadvantage of using const reference when iterating over basic types?
Can I easily iterate over the values of a map using a range-based for loop?

कृपया पर ध्यान केंद्रित:


अद्यतन दो उदाहरण है कि मैं अपने पसंदीदा में पाया (shared_ptr अस्पष्ट कोने मामलों के लिए एक संदिग्ध है) प्रश्न: मैं क्यों उपयोग करना चाहता हूं ऑटो & & लूप के लिए श्रेणी-आधारित में?

+3

क्या आप इसे "अक्सर" देखते हैं? –

+2

मुझे यकीन नहीं है कि मेरे प्रश्न में पर्याप्त संदर्भ है कि यह जानने के लिए कि "पागल" यह कहां है जहां आप इसे देख रहे हैं। –

+2

@LightnessRacesinOrbit लंबी कहानी छोटी: मैं लूप के लिए श्रेणी-आधारित में 'ऑटो &&' का उपयोग क्यों करना चाहूंगा? – Ali

उत्तर

64

एकमात्र लाभ जो मैं देख सकता हूं वह है जब अनुक्रम इटरेटर प्रॉक्सी संदर्भ देता है और आपको उस संदर्भ पर एक गैर-कॉन्स तरीके से काम करने की आवश्यकता होती है। उदाहरण के लिए विचार करें:

#include <vector> 

int main() 
{ 
    std::vector<bool> v(10); 
    for (auto& e : v) 
     e = true; 
} 

यह संकलन नहीं है क्योंकि rvalue vector<bool>::referenceiterator से लौटे एक गैर स्थिरांक lvalue संदर्भ के लिए बाध्य नहीं होंगे। लेकिन इस काम करेगा:

#include <vector> 

int main() 
{ 
    std::vector<bool> v(10); 
    for (auto&& e : v) 
     e = true; 
} 

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

#include <vector> 

int main() 
{ 
    std::vector<bool> v(10); 
    // using auto&& so that I can handle the rvalue reference 
    // returned for the vector<bool> case 
    for (auto&& e : v) 
     e = true; 
} 

संपादित

मेरा यह आखिरी मामला: और अगर मैं यह कर किया था, यह क्यों के रूप में एक टिप्पणी शामिल करने के लिए चोट नहीं होगा। यदि आप जानते हैं कि लूप हमेशा प्रॉक्सी संदर्भ को संभालने वाला है, तो auto काम करेगा साथ ही साथ auto&&। लेकिन जब लूप कभी-कभी गैर-प्रॉक्सी संदर्भों और कभी-कभी प्रॉक्सी-संदर्भों को संभालने में था, तो मुझे लगता है कि auto&& पसंद का समाधान बन जाएगा।

+2

दूसरी ओर, कोई स्पष्ट _disadvantage_ नहीं है, है ना? (संभावित रूप से भ्रमित लोगों के अलावा, जो मुझे नहीं लगता है, व्यक्तिगत रूप से उल्लेखनीय है।) – ildjarn

+0

यह एक दिलचस्प बात है। संभवतः 'टी :: const_iterator' को प्राथमिकता देने के लिए'for'' को प्रोत्साहित करने का कोई तरीका नहीं है? मेरा मानना ​​है कि 'शुरू() 'और' अंत()' का उपयोग किया जाता है। एक निरीक्षण की थोड़ी सी लगती है, सिवाय इसके कि आप रावल्यू रेफ का उपयोग कर सकते हैं। तो हाँ शायद यह जवाब है। –

+3

कोड लिखने के लिए एक और शब्द जो अनावश्यक रूप से लोगों को भ्रमित करता है: भ्रमित कोड लिखना। अपने कोड को यथासंभव सरल बनाना सर्वोत्तम है, लेकिन कोई आसान नहीं है। इससे बग गिनती को कम रखने में मदद मिलेगी। ऐसा कहा जा रहा है, क्योंकि && अधिक परिचित हो जाता है, तो अब से 5 साल लोग एक ऑटो और मुहावरे (यह मानते हैं कि वास्तव में कोई नुकसान नहीं होता है) की उम्मीद होगी। मुझे नहीं पता कि यह होगा या नहीं। लेकिन दर्शक की नजर में सरल है, और यदि आप अपने आप से अधिक के लिए लिख रहे हैं, तो अपने पाठकों को ध्यान में रखें। –

19

auto&& या universal references एक सीमा के आधार पर for -loop साथ का उपयोग करना है कि आप कब्जा आप क्या मिलता है लाभ दिया है। अधिकांश प्रकार के इटरेटर्स के लिए आपको शायद T& या T const& किसी प्रकार के T के लिए शायद T& मिल जाएगा। दिलचस्प मामला यह है कि एक पुनरावर्तक को अस्वीकार करने से अस्थायी पैदा होता है: सी ++ 2011 को आराम की आवश्यकताएं मिलती हैं और इटेटर को आवश्यक रूप से एक लाभा उत्पन्न करने की आवश्यकता नहीं होती है।सार्वभौमिक संदर्भ का उपयोग std::for_each() में तर्क अग्रेषण मेल खाता है:

template <typename InIt, typename F> 
F std::for_each(InIt it, InIt end, F f) { 
    for (; it != end; ++it) { 
     f(*it); // <---------------------- here 
    } 
    return f; 
} 

समारोह वस्तु fT&, T const&, और T अलग ढंग से इलाज कर सकते हैं। एक श्रेणी-आधारित for -loop का शरीर अलग क्यों होना चाहिए? ,

for (auto&& x: range) { 
    f(std::forward<decltype(x)>(x)); 
} 
बेशक

का उपयोग कर std::forward() मतलब यह है कि आप किसी भी लौटे मूल्यों से स्थानांतरित करने स्वीकार करते हैं: बेशक, वास्तव में उन्हें तदनुसार पर पारित करने के लिए प्रकार सार्वभौमिक संदर्भ की जरूरत है, उसका उपयोग निष्कर्ष निकाला होने का लाभ लेने के। क्या इस तरह की वस्तुएं गैर-टेम्पलेट कोड में बहुत अधिक समझ में आती हैं जो मुझे नहीं पता (अभी तक?)। मैं कल्पना कर सकता हूं कि सार्वभौमिक संदर्भों का उपयोग करने से कंपाइलर को सही चीज करने के लिए अधिक जानकारी मिल सकती है। Templated कोड में यह वस्तुओं के साथ क्या होना चाहिए पर कोई निर्णय लेने से बाहर रहता है।

5

मैं लगभग auto&& का उपयोग करता हूं। जब आपको नहीं करना है तो किनारे के मामले से क्यों काट लें? यह भी टाइप करने के लिए छोटा है, और मैं बस इसे और अधिक ... पारदर्शी पाते हैं। जब आप auto&& x का उपयोग करते हैं, तो आप जानते हैं कि x हर समय *it है।

+20

मेरी समस्या यह है कि आप 'ऑटो' और 'स्थिर' और 'पर्याप्त' होने पर 'ऑटो' और 'के साथ 'const'-ness दे रहे हैं। सवाल कोने के मामलों के लिए पूछता है जहां मैं काटा जा सकता है। कोने के मामले क्या हैं जिनका उल्लेख अभी तक डाइटमार या हॉवर्ड द्वारा नहीं किया गया है? – Ali

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

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