2017-09-20 15 views
9
#include <iostream> 
#include <algorithm> 
#include <vector> 

int main() 
{ 
    // Block 1 
    { 
    auto inc = []() { int i = 0; return [&]() { return i++; }; }(); 
    std::vector<int> v(10, 10); 
    std::generate(v.begin(), v.end(), inc); 
    for (auto i : v) std::cout << i << std::endl; 
    } 

    // Block 2 
    { 
    auto inc = []() { int i = 0; return [&]() { return i++; }; }; 
    std::vector<int> v(10, 10); 
    std::generate(v.begin(), v.end(), inc()); 
    for (auto i : v) std::cout << i << std::endl; 
    } 
} 

मुझे यकीन नहीं है कि ये दो ब्लॉक अलग-अलग परिणाम क्यों उत्पन्न करते हैं।सी ++ लैम्ब्डा

Block 1: 32767 ... 32776 
Block 2: 0 ... 10 

और std::generate जनरेटर (inc) मूल्य से पारित हो जाता है, तो मेरा मानना ​​है कि यह ठीक होना चाहिए अधिकार के लिए?

मैं ओएस एक्स चला रहा हूँ

धन्यवाद,


ध्यान दें कि कोड से परिणाम अपरिभाषित हैं, नीचे देखें।

+0

पुन: पेश नहीं किया जा सकता है, जीसीसी v5.1.0 दोनों मामलों में एक ही आउटपुट उत्पन्न करता है – Slava

+0

मैं क्लैंग संस्करण 3.6.2 के साथ संकलित कर रहा हूं। – Ling

+1

कभी नहीं, यह यूबी है, इसलिए विशेष आउटपुट अप्रासंगिक है – Slava

उत्तर

10

मुझे यकीन नहीं है कि ये दो ब्लॉक अलग-अलग परिणाम क्यों उत्पन्न करते हैं।

दोनों अपरिभाषित व्यवहार हैं, इसलिए सवाल मंथन है।

auto f = []() { int i = 0; return [&]() { return i++; }; }; 

और f() रिटर्न एक लैम्ब्डा एक झूलने संदर्भ में है कि: if को कॉल के अंत में नष्ट हो जाता है या तो मामले में, हम एक लैम्ब्डा की तरह है। यह है जब कि संदर्भ लटकता हुआ होता है - चाहे यह generate() कॉल से पहले या generate() कॉल में बहुत पहले होता है।

आप एक लैम्ब्डा के साथ एक पैदा काउंटर बनाना चाहते हैं, सीधा रास्ता लैम्ब्डा परिवर्तनशील और उपयोग init पर कब्जा करने के लिए है:

auto inc = [i=0]() mutable { return i++; }; 

mutable आवश्यकता है क्योंकि lambdas const डिफ़ॉल्ट रूप से कर रहे हैं, और हमें सदस्य i को सीधे संशोधित करने की आवश्यकता है।


उपरोक्त सी ++ 14 (सामान्यीकृत इनिट-कैप्चर के कारण) है। हम मान द्वारा कब्जा करने के लिए सी ++ 11 बस संदर्भ द्वारा भीतरी लैम्ब्डा कैप्चरिंग से नेस्टेड-लैम्ब्डा संरचना को बदलने के द्वारा इस काम कर सकता है:

auto inc = []{ int i = 0; return [=]() mutable { return i++; }; }(); 
//        ~~~ ~~~~~~~ 

है यही कारण है कि ... अप्रिय की तरह है, लेकिन यह काम करता है?

+0

क्या [i = 0] सी ++ 14 की आवश्यकता है? – Slava

+0

@ स्लावा हां, अभी भी सी ++ 11 में काम करने के लिए ओपी के मूल नेस्टेड-लैम्ब्डा उदाहरण को ठीक करने का एक तरीका जोड़ा गया है। – Barry

+0

धन्यवाद, क्योंकि 'i'' ऑपरेटर() 'के अंदर एक स्थानीय अस्थायी वस्तु है, यदि आपको लगता है कि लैम्ब्डा' संरचना 'की तरह है। इस प्रकार लौटा लम्बा कैप्चर स्थानीय चर के लिए एक अवैध संदर्भ है। यही कारण है कि दोनों मामले यूबी हैं। पहले मैंने सोचा कि यह असली बंद होने की तरह व्यवहार करेगा। – Ling

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