2015-03-06 8 views
5

विशेष रूप से कोड है। लाइन 15 क्या कर रहा है (बदलने के लिए कॉल)?[] const_iterator :: value_type std :: में परिवर्तन

क्या कोई यह बता सकता है कि यहक्यों आउटपुट करता है? दूसरी ओर यदि मैं लाइन 15 में सीबी ++ सीबी में बदलता हूं, तो यह 01110 आउटपुट करता है। लाइन 15 पर रिटर्न वैल्यू क्या है?

#include <algorithm> 
#include <functional> 
#include <iostream> 
#include <iterator> 
#include <list> 

int main() 
{ 
    typedef std::list<int> L; 
    L l(5); 

    typedef L::const_iterator CI; 
    CI cb = l.begin(), ce = l.end(); 
    typedef L::iterator I; 
    I b = l.begin(); 
    std::transform(cb, --ce, ++b, [] (CI::value_type n) { return ++n; }); 
    std::copy(l.begin(), l.end(), std::ostream_iterator<CI::value_type>(std::cout)); 
    std::cout << std::endl; 

    return 0; 
} 
+5

यह कोड अनावश्यक रूप से जटिल होगा। Typedefs कोई स्पष्टीकरण नहीं जोड़ता है और परिवर्तनीय नाम उपयोगी नहीं हैं। –

+0

'सीआई :: value_type' यहां 'int' होने की बहुत अधिक गारंटी है। कुछ परिवर्तनीय घोषणाओं को स्पष्ट करने के लिए 'ऑटो' का भी उपयोग किया जा सकता है। –

+0

क्या आप पूछ रहे हैं कि [lambda] (http://en.cppreference.com/w/cpp/language/lambda) क्या है? –

उत्तर

2

इस बयान

L l(5); 

वहाँ जिनमें से प्रत्येक 0.

से आरंभ नहीं हो जाता 5 तत्वों की सूची बनाई गई है में: आप n+1 अभिव्यक्ति है, जो कोई साइड प्रभाव पड़ता है के साथ बदल सकते हैं

इस कॉल में

std::transform(cb, --ce, ++b, [] (CI::value_type n) { return ++n; }); 

cb अंक सूची का पहला तत्व। मूल्यांकन के बाद --ce कमी ऑपरेटर सूची के अंतिम तत्व को इंगित करता है। इस प्रकार cb और सूची

[cb, --ce) 

के तत्वों में से --ce सेट रेंज जहां कोष्टक मतलब यह है कि --ce सीमा में शामिल नहीं है।

++b सूची के दूसरे तत्व में वृद्धि बिंदुओं के मूल्यांकन के बाद। तो आप

b 
    | 
0 0 0 0 0 
^  ^
|  | 
cb  ce 

मूल्य सीबी सूची के पहले तत्व का मूल्य है कि लैम्ब्डा अभिव्यक्ति

[] (CI::value_type n) { return ++n; } 

में वृद्धि हुई है और का दूसरा तत्व में लिखा है द्वारा की ओर इशारा किया सूची इटेटर बी द्वारा इंगित की गई। उसके बाद cb और b परिवर्तन के शरीर के भीतर वृद्धि हुई है।

तो सबसे पहले यात्रा के बाद सूची सूची का दूसरा तत्व को

तरह
b 
    | 
0 1 0 0 0 
^ ^
    |  | 
    cb ce 

अब cb अंक लग रहा है। इसका मूल्य लैम्ब्डा अभिव्यक्ति में बढ़ता है और तीसरे तत्व में लिखा जाता है जो इटरेटर b द्वारा इंगित किया जाता है।

 b 
     | 
0 1 2 0 0 
    ^^
    | | 
    cb ce 

नतीजतन आप उस सूची मिल जाएगा मान 0, 1, 2, 3 होगा, 4.

आप की तरह

std::transform(++cb, --ce, ++b, [] (CI::value_type n) { return ++n; }); 

एल्गोरिथ्म के कॉल लिखेंगे अगर वह ++cb का उपयोग कर रहा है तो cb और b उसी तत्व को इंगित करेगा और एल्गोरिदम बस प्रत्येक तत्व को सूची के दूसरे तत्व से शुरू होने वाले इसके बढ़ते मूल्य के साथ फिर से लिख देगा क्योंकि इटरेटर ++cb का उपयोग किया गया था। परिणाम 0, 1, 1, 1, 0

+0

उत्कृष्ट विवरण पोस्ट किया। धन्यवाद! – VarsMolta

4

अभिव्यक्ति [](CI:value_type n) { return ++n; } एक लैम्ब्डा कार्य है। खाली ब्रैकेट का मतलब है कि यह वर्तमान दायरे के किसी भी सदस्य तक नहीं पहुंचता है।

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

कोड दूसरे के बाद एल का एक तत्व लेता है और इसे एल के अगले तत्व (++ बी के कारण) में बढ़ाता है। इसलिए आपको 0, 1, 2, 3, 4.

यदि आप ++ cb में cb बदलते हैं, तो आपको 0, 1, 1, 1, 0 मिलता है क्योंकि तब आप इंडेक्स 1 के साथ तत्व पर प्रारंभ करते हैं और बस पिछले एक से पहले तक प्रत्येक एक वृद्धि।

Find some information about lambdas here.

Explanation of std::transform

1

सबसे पहले, आप वाक्य रचना के माध्यम से प्राप्त करने की आवश्यकता: वर्ग कोष्ठक बताते हैं कि आपका लैम्ब्डा समारोह उसके आसपास के संदर्भ से कुछ भी कब्जा नहीं है। असल में, std::transform के कॉल में तर्क के एक टुकड़े में प्लगिंग का यह एक संक्षिप्त तरीका है: आप उस फ़ंक्शन को बताते हैं जो एक मूल्य को बदलने का मतलब है उसे जोड़ना। ,, यह आइटम cb से (प्रारंभिक तत्व) --ce अप करने के लिए (पीछे से दूसरा तत्व) लेता समावेशी:

आगे समझने के लिए क्या चल रहा है, और यह भी 01110 उत्पादन समझाने के लिए, चलो देखते हैं कि क्या std::transform करता है चलो लैम्ब्डा फ़ंक्शन को कॉल करता है, और परिणामस्वरूप यह ++b से शुरू होने वाली कोशिकाओं में लौटाता है, यानि इंडेक्स 1, 2, 3, आदि।

पहला पुनरावृत्ति L[0] से शून्य लेता है, एक जोड़ता है, और 1L[1] में लिखता है। दूसरा पुनरावृत्ति 1 पहले से उठाता है, एक जोड़ता है, और 2L[2] में लिखता है। पुनरावृत्ति तब तक जारी है जब तक std::transform4L[4] में लिखता है।

जब आप ++cb साथ cb की जगह है, तथापि, लेखन एक ही सेल जहाँ से डेटा को पढ़ने गया था में, यानी L[1] सौंप दिया जाता है 0+1 तो L[2] सौंप दिया जाता है 0+1 पाश किया जाता है, तो L[3] सौंप दिया जाता है 0+1, और उसके बाद --ce तक पहुंचता है, और बंद हो जाता है।

ध्यान दें कि ++n अनावश्यक है, क्योंकि n बढ़ने का दुष्प्रभाव लैम्बडा कॉल खत्म हो जाने पर गायब हो जाता है।

std::transform(cb, --ce, ++b, [] (CI::value_type n) { return n+1; }); 
संबंधित मुद्दे