2012-10-03 16 views
23

मैं कोड है कि एक shared_from_this() पर कब्जा करने पर निर्भर करता है जब एक कॉलबैक के रूप में एक लैम्ब्डा अभिव्यक्ति का उपयोग कर यह सुनिश्चित करें कि मेरी उदाहरण रहता है की एक सभ्य राशि जिंदा:सी ++: क्या एक अप्रयुक्त लैम्ब्डा स्पष्ट कैप्चर अनुकूलित किया जा सकता है?

std::shared_ptr<Thing> self = shared_from_this(); 
auto doSomething = [this, self]() 
{ 
    // various statements, none of which reference self, but do use this 
} 

तो सवाल यह है: जब से मैं self अंदर संदर्भित नहीं कर रहा हूँ लैम्ब्डा बॉडी, कैप्चर को अनुकूलित करने के लिए एक अनुरूप कंपेलर है?


पर विचार करें निम्नलिखित कार्यक्रम:

#include <functional> 
#include <iostream> 
#include <memory> 

std::function<void()> gFunc; 

struct S : std::enable_shared_from_this<S> 
{ 
    void putGlobal() 
    { 
     auto self = shared_from_this(); 
     gFunc = [self] { }; 
    } 
}; 

int main() 
{ 
    auto x = std::make_shared<S>(); 
    std::cout << x.use_count() << std::endl; 
    x->putGlobal(); 
    std::cout << x.use_count() << std::endl; 
} 

उत्पादन होता है:

1 
2 

यह बताता है कि g++-4.7.1 कब्जा दूर अनुकूलन नहीं करता (और न ही clang-3.1 करता है)।

उत्तर

30

मानक गारंटी देता है कि कब्जा कर लिया मूल्यों दूर अनुकूलित नहीं हैं (प्रति §5.1.2/14):

एक इकाई प्रतिलिपि द्वारा कब्जा कर लिया गया है, तो यह परोक्ष कब्जा कर लिया है और कब्जा-डिफ़ॉल्ट है = या यदि यह स्पष्ट रूप से पर कब्जा कर लिया गया है कैप्चर के साथ जिसमें & शामिल नहीं है। प्रतिलिपि द्वारा कब्जा कर लिया गया प्रत्येक इकाई के लिए, एक अज्ञात गैर- स्थैतिक डेटा सदस्य बंद प्रकार में घोषित किया जाता है। इन सदस्यों की घोषणा आदेश अनिर्दिष्ट है। ऐसे डेटा सदस्य का प्रकार संबंधित कैप्चर किए गए इकाई का प्रकार है यदि इकाई किसी ऑब्जेक्ट के संदर्भ में नहीं है, या संदर्भित प्रकार अन्यथा है।

तो, self मूल्यांकन पर बंद में बनाई जाए (प्रति §5.1.2/21):

जब लैम्ब्डा अभिव्यक्ति मूल्यांकन किया जाता है, संस्थाओं है कि नकल से कब्जा कर लिया है करने के लिए उपयोग किया जाता है परिणामी बंद करने वाली वस्तु के प्रत्येक संबंधित गैर स्थैतिक डेटा सदस्य को प्रत्यक्ष-प्रारंभ करें।

+1

ऐसा लगता है [यह उत्तर] (http://stackoverflow.com/questions/6181464/c11-lambda-capture-semantics), जो कहता है कि अगर यह ओडीआर अप्रयुक्त है तो यह वास्तव में कब्जा नहीं किया जाता है। – GManNickG

+9

@GManNickG: अंतर अंतर्निहित कैप्चरिंग ('[=]') और * स्पष्ट * कैप्चरिंग ('[someNameHere]') का अंतर है। लागू कैप्चरिंग के लिए ओडीआर प्रयुक्त तत्वों की आवश्यकता होती है। स्पष्ट कैप्चरिंग नहीं है। –

+0

@ निकोलबोलस: गोचा। यदि एक इकाई का उपयोग किया जाता है तो केवल एक इकाई को पूरी तरह से कब्जा कर लिया जाता है। उस बिंदु पर, यह स्पष्ट रूप से कब्जा कर लिया गया इकाइयों के समान नाव में है। धन्यवाद। – GManNickG