2013-08-28 8 views
8

पर विचार करें निम्नलिखित सी ++ विधि:उद्देश्य सी ++ ब्लॉक अर्थ विज्ञान

class Worker{ 
.... 
private Node *node 
}; 

void Worker::Work() 
{ 
    NSBlockOperation *op=[NSBlockOperation blockOperationWithBlock: ^{ 
      Tool hammer(node); 
      hammer.Use(); 
      }]; 
    .... 
    } 

क्या, वास्तव में, ब्लॉक पर कब्जा जब यह कब्जा "नोड" करता है? ब्लॉक, http://clang.llvm.org/docs/BlockLanguageSpec.html के लिए भाषा का विनिर्देश, अन्य मामलों के लिए स्पष्ट है:

यौगिक बयान के दायरे के भीतर इस्तेमाल किया चर स्वत: (ढेर) भंडारण में उन लोगों के अपवाद के साथ सामान्य तरीके से ब्लॉक करने के लिए बाध्य कर रहे हैं। इस प्रकार कोई व्यक्ति फ़ंक्शंस और ग्लोबल वेरिएबल्स तक पहुंच सकता है जैसा कि कोई उम्मीद करेगा, साथ ही साथ स्थिर स्थानीय चर। [testme]

ब्लॉक के कंपाउंड स्टेटमेंट के संदर्भ में स्थानीय स्वचालित (स्टैक) चर संदर्भित और अवरुद्ध प्रतियों के रूप में ब्लॉक द्वारा कब्जा कर लिया जाता है।

लेकिन यहां, क्या हम के वर्तमान मूल्य को इस पर कैप्चर करते हैं? की एक प्रति इस वर्कर की कॉपी कन्स्ट्रक्टर का उपयोग कर? या उस स्थान का संदर्भ जहां नोड संग्रहीत है?

विशेष रूप से, हम कहते हैं

{ 
Worker fred(someNode); 
fred.Work(); 
} 

वस्तु fred किसी भी अधिक मौजूद नहीं हो सकता है जब ब्लॉक चलाने हो जाता है लगता है। नोड का मूल्य क्या है? (मान लें कि अंतर्निहित नोड वस्तुओं हमेशा के लिए रहते हैं, लेकिन श्रमिक आते हैं और जाते।)

, तो इसके बजाय हम लिखा

void Worker::Work() 
    { 
     Node *myNode=node; 
     NSBlockOperation *op=[NSBlockOperation blockOperationWithBlock: ^{ 
       Tool hammer(myNode); 
       hammer.Use(); 
       }]; 
     .... 
     } 

परिणाम अलग है?

+0

सी ++ प्रकारों के बेहतर कैप्चरिंग अर्थशास्त्र के लिए सी ++ 11 लैम्बडा पर विचार करें। – justin

+0

@justin: यह कैसे बेहतर है? एक सी ++ लैम्ब्डा मूल्य से 'यह' भी कैप्चर करेगा और सटीक वही अर्थशास्त्र होगा। – newacct

+0

@ न्यूवेक्ट मैंने कभी लिखा नहीं है "इस 'के बेहतर कैप्चरिंग अर्थशास्त्र के लिए सी ++ 11 लैम्बडा पर विचार करें। हालांकि, एक अंतर यह है कि 'यह' ** ** ** ** लम्बास के साथ पूरी तरह से कब्जा नहीं किया गया है, जो एक अच्छा बचाव है। – justin

उत्तर

8

this page के अनुसार:

सामान्य तौर पर आप एक ब्लॉक के भीतर सी ++ ऑब्जेक्ट का उपयोग कर सकते हैं। सदस्य फ़ंक्शन के भीतर, सदस्य चर और फ़ंक्शंस के संदर्भ के माध्यम से अंतर्निहित this पॉइंटर आयातित होते हैं और इस प्रकार उत्परिवर्तनीय दिखाई देते हैं।

  • आप क्या एक ढेर आधारित सी ++ वस्तु हो गया होता के लिए एक __block भंडारण वर्ग है, तो हमेशा की तरह प्रति निर्माता प्रयोग किया जाता है: वहाँ दो विचार हैं जिनका लागू करता है, तो एक ब्लॉक की नकल की है।
  • यदि आप ब्लॉक के भीतर से किसी अन्य सी ++ स्टैक-आधारित ऑब्जेक्ट का उपयोग करते हैं, तो उसे में एक कॉन्स कॉपी कन्स्ट्रक्टर होना चाहिए। सी ++ ऑब्जेक्ट को तब का उपयोग करके कॉपी किया गया है जो कि कन्स्ट्रक्टर है।

अनुभव से, मुझे लगता है कि ब्लॉक में यह स्थिरांक प्रतियां this सूचक का पालन। यदि C++ उदाहरण this द्वारा इंगित किया गया है तो ब्लॉक उस निष्पादन पर नहीं है जब ब्लॉक निष्पादित होता है (उदाहरण के लिए, यदि वर्कर इंस्टेंस पर Worker::Work() कहा जाता है तो उच्च फ्रेम पर स्टैक-आवंटित किया गया था), तो आपको एक EXC_BAD_ACCESS या इससे भी बदतर मिलेगा (यानी पॉइंटर एलियासिंग)।तो ऐसा प्रतीत होता है कि:

  • यह this पर कब्जा कर रहा है, मूल्य द्वारा आवृत्ति चर की प्रतिलिपि नहीं बना रहा है।
  • वस्तु को this जीवित रखने के लिए कुछ भी नहीं किया जा रहा है।

वैकल्पिक रूप से, अगर मैं एक स्थानीय स्तर पर स्टैक-आवंटित (यानी इस ढेर फ्रेम/दायरे में घोषित) सी ++ वस्तु संदर्भ में, मैं देख सकते हैं कि इसकी प्रतिलिपि निर्माता जब यह शुरू में ब्लॉक द्वारा कब्जा कर लिया है कहा जाता हो जाता है, और उसके बाद फिर जब भी ब्लॉक (उदाहरण के लिए, आपरेशन कतार से जब आप आपरेशन enqueue।) की नकल की है

आपके प्रश्नों का विशेष रूप से समाधान करने के लिए:

लेकिन यहाँ, हम this के वर्तमान मूल्य पर कब्जा करते हैं? वर्कर की कॉपी कन्स्ट्रक्टर का उपयोग करके इसकी एक प्रति? या उस स्थान का संदर्भ जहां नोड संग्रहीत किया जाता है?

हम this पर कब्जा करते हैं। अगर यह मदद करता है तो intptr_t की एक कॉन्स-कॉपी पर विचार करें।

ऑब्जेक्ट fred ब्लॉक चलाए जाने पर अब और मौजूद नहीं हो सकता है। node का मूल्य क्या है? (मान लें कि अंतर्निहित नोड वस्तुओं हमेशा के लिए रहते हैं, लेकिन श्रमिक आते हैं और जाते।)

इस मामले में, this दर-मूल्य पर कब्जा कर लिया गया है और node प्रभावी रूप से मूल्य this + <offset of node in Worker> साथ एक सूचक है लेकिन जब से कार्यकर्ता उदाहरण है चला गया, यह प्रभावी रूप से एक कचरा सूचक है।

मैं उन दस्तावेज़ों में वर्णित किसी भी जादू के अलावा कोई जादू या अन्य व्यवहार नहीं करता।

1

सी ++ में, जब आप एक उदाहरण चर node लिखते हैं, स्पष्ट रूप से something->node लिखने के बिना, यह स्पष्ट रूप से this->node है। (कैसे ऑब्जेक्टिव-सी में, यदि आप स्पष्ट रूप से something->node लेखन के बिना एक उदाहरण चर node, लिखते हैं, यह परोक्ष self->node है की तरह।)

तो चर जो किया जा रहा है this है, और यह this कि कब्जा कर लिया जाता है। (तकनीकी रूप से this मानक में एक अलग अभिव्यक्ति प्रकार के रूप में वर्णित है, एक चर नहीं; लेकिन सभी उद्देश्यों और उद्देश्यों के लिए यह Worker *const प्रकार के एक अंतर्निहित स्थानीय चर के रूप में कार्य करता है।) सभी गैर-__block चर के साथ, इसे कैप्चर करने से constthis की प्रति।

ब्लॉक में मेमोरी मैनेजमेंट सेमेन्टिक्स होते हैं जब वे ऑब्जेक्टिव-सी ऑब्जेक्ट पॉइंटर प्रकार के चर को कैप्चर करते हैं। हालांकि, this में उद्देश्य-सी ऑब्जेक्ट पॉइंटर प्रकार नहीं है, इसलिए स्मृति प्रबंधन के संदर्भ में इसके साथ कुछ भी नहीं किया जाता है। (ऐसा कुछ भी नहीं है जो सी ++ मेमोरी मैनेजमेंट के मामले में किया जा सकता है।) तो हां, सी ++ ऑब्जेक्ट this द्वारा इंगित किया गया है जब तक ब्लॉक चलता है।

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