2010-08-01 15 views
7

में ट्रैकिंग संदर्भ कृपया कोई मुझे निम्नलिखित कोड स्निपेट समझा सकता है?सी ++/सीएलआई

value struct ValueStruct { 
    int x; 
}; 

void SetValueOne(ValueStruct% ref) { 
    ref.x = 1; 
} 

void SetValueTwo(ValueStruct ref) { 
    ref.x = 2; 
} 

void SetValueThree(ValueStruct^ ref) { 
    ref->x = 3; 
} 

ValueStruct^ first = gcnew ValueStruct; 
first->x = 0; 
SetValueOne(*first); 

ValueStruct second; 
second.x = 0; 
SetValueTwo(second); // am I creating a copy or what? is this copy Disposable even though value types don't have destructors? 

ValueStruct^ third = gcnew ValueStruct; 
third->x = 0; 
SetValueThree(third); // same as the first ? 

और मेरी दूसरी सवाल यह है: वहाँ कि ?: की तरह कुछ है करने के लिए किसी भी कारण है

ref struct RefStruct { 
    int x; 
}; 

RefStruct% ref = *gcnew RefStruct; 
// rather than: 
// RefStruct^ ref = gcnew RefStruct; 

// can I retrieve my handle from ref? 
// RefStruct^ myref = ??? 

और क्या है: मैं, मान प्रकार और रेफरी प्रकार के बीच कोई अंतर देखने के बाद से दोनों हो सकता है हैंडलर द्वारा निर्देशित; (

उत्तर

24

याद रखें कि सी ++/सीएलआई का प्राथमिक उपयोग अन्य .NET भाषाओं में जीयूआई/वेब सेवाओं द्वारा खपत के लिए कक्षा पुस्तकालयों के विकास के लिए है। इसलिए सी ++/सीएलआई को संदर्भ और मूल्य प्रकार दोनों का समर्थन करना है क्योंकि अन्य .NET भाषाएं करते हैं।

इसके अलावा, सी # में ref पैरामीटर हो सकते हैं जो मूल्य टाइप किए गए हैं, यह सी ++/सीएलआई के लिए अद्वितीय नहीं है और यह किसी भी तरह से संदर्भ प्रकारों के बराबर मूल्य प्रकार नहीं बनाता है।

मैं एक प्रतिलिपि या क्या बनाने हूँ:

अपने कोड टिप्पणी में सवालों के जवाब देने के लिए?

हां, SetValueTwo मूल्य से अपना पैरामीटर लेता है, इसलिए एक प्रतिलिपि बनाई जाती है।

यह प्रतिलिपि डिस्पोजेबल है भले ही मूल्य प्रकारों में विनाशक नहीं हैं?

गलत। मूल्य प्रकारों में विनाशक हो सकते हैं। मूल्य प्रकारों में अंतिमकर्ता नहीं हो सकते हैं। चूंकि इस विशेष मूल्य प्रकार में एक छोटा विनाशक होता है, इसलिए सी ++/सीएलआई कंपाइलर इसे IDISposable लागू करने का कारण नहीं बनता है। किसी भी मामले में, यदि कोई पैरामीटर एक आईडीस्पोजेबल मान प्रकार है, तो C++/CLI कंपाइलर यह सुनिश्चित करेगा कि जब वेरिएबल स्कोप से बाहर हो जाए तो निपटान कहा जाता है, जैसे स्थानीय चर के लिए स्टैक अर्थशास्त्र की तरह। इसमें असामान्य समाप्ति (फेंक दिया गया अपवाद) शामिल है, और प्रबंधित प्रकारों को आरएआईआई के साथ उपयोग करने की अनुमति देता है।

दोनों

ValueStruct% ref = *gcnew ValueStruct; 

और

ValueStruct^ ref = gcnew ValueStruct; 

अनुमति दी जाती है, और (प्रबंधित ढेर पर एक बॉक्स्ड मान प्रकार उदाहरण रखा जो एक ढेर बिल्कुल नहीं है, लेकिन एक ढेर, लेकिन यह कॉल स्टैक नहीं है जहां स्थानीय चर संग्रहीत किए जाते हैं, इसलिए माइक्रोसॉफ्ट इसे डायनामिक आवंटन के लिए देशी मेमोरी एरिया की तरह एक ढेर कहने का विकल्प चुनता है)।

सी # के विपरीत, सी ++/सीएलआई टाइप किए गए हैंडल को बॉक्स किए गए ऑब्जेक्ट्स में रख सकता है।

यदि ट्रैकिंग संदर्भ किसी अन्य ऑब्जेक्ट में स्टैक या एम्बेडेड पर मान प्रकार के उदाहरण के लिए है, तो मान प्रकार की सामग्री को संदर्भित करने की प्रक्रिया में बॉक्स किया जाना चाहिए।

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

RefClass^ newinst = gcnew RefClass(); 
RefClass% reftoinst = *newinst; 
RefClass^% reftohandle = newinst; 

RefClass stacksem; 
RefClass^ ssh = %stacksem; 

एक बात है कि मैं पूरी तरह से याद करने लगते हैं कभी नहीं हो सकता है कि वाक्य रचना 100 नहीं है % देशी सी ++ की तुलना में लगातार संगत।

एक संदर्भ घोषित:

int* pi; // native 
Stream^ sh; // tracking handle 

फार्म एक सूचक:

int& ri = i; // native 
DateTime% dtr = dt; // managed tracking reference 

एक सूचक घोषित

int* pi = &ri; // address-of native object 
DateTime^ dth = %dtr; // address-of managed object 

ध्यान दें कि एकल पते के ऑपरेटर के रूप में ही है मानक सी ++ और सी ++/सीएलआई दोनों में संदर्भ नोटेशन। ऐसा लगता है कि a tracking reference cannot be used as a unary take-address operator (MSDN) का विरोध है जो मैं एक सेकंड में वापस आऊंगा।

हालांकि सबसे पहले, विसंगति:

फार्म एक सूचक से एक संदर्भ:

int& iref = *pi; 
DateTime% dtref = *dth; 

ध्यान दें कि एकल भिन्नता ऑपरेटर हमेशा होता है *। यह केवल मूल दुनिया में सूचक संकेत के समान है, जो उपरोक्त वर्णित पते के बिल्कुल विपरीत है, संदर्भ संदर्भ के रूप में हमेशा एक ही प्रतीक है।

compilable उदाहरण:

DateTime^ dth = gcnew DateTime(); 
DateTime% dtr = *dth; 

DateTime dt = DateTime::Now; 
DateTime^ dtbox = %dt; 

FileInfo fi("temp.txt"); 
// FileInfo^ fih = &fi; causes error C3072 
FileInfo^ fih = %fi; 

अब, एकल पता-के बारे में:

पहले, MSDN लेख गलत है जब यह कहते हैं:

निम्न नमूना से पता चलता है कि एक ट्रैकिंग संदर्भ को एक यूनरी ले-एड्रेस ऑपरेटर के रूप में उपयोग नहीं किया जा सकता है।

सही कथन है:

% एक ट्रैकिंग संभाल के निर्माण के लिए पता-के ऑपरेटर है। हालांकि इसका उपयोग इस प्रकार सीमित है:

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

उदाहरण कोड:

int i = 5; 
// int^ ih = %i; causes error C3071 

System::Int32 si = 5; 
// System::Int32^ sih = %si; causes error C3071 
// error C3071: operator '%' can only be applied to an instance 
//    of a ref class or a value-type 

हैं System::Int32 एक मान प्रकार तो मैं क्या पता नहीं है नहीं है। के System::DateTime कोशिश जो एक गैर आदिम मान प्रकार है दो:

DateTime dt = DateTime::Now; 
DateTime^ dtbox = %dt; 

यह काम करता है!

एक और दुर्भाग्यपूर्ण प्रतिबंध के रूप में, आदिम प्रकार जिनके पास दोहरी पहचान है (उदा।देशी int और प्रबंधित मूल्य प्रकार System::Int32) सही ढंग से संभाला नहीं जाता है, % (फ़ॉर्म ट्रैकिंग संदर्भ) ऑपरेटर मुक्केबाजी निष्पादित नहीं कर सकता है, भले ही प्रकार के .NET नाम दिए गए हों।

+0

क्या आप सुनिश्चित हैं कि "RefStruct^ref = gcnew RefStruct;" (जहां रेफस्ट्रक्चर संदर्भ प्रकार का है) एक बॉक्सिंग मूल्य प्रकार उदाहरण ढेर पर रखता है? और ऊपर की रेखा में आपको गलती है, क्या आपका मतलब है^gcnew के बजाय gcnew? –

+0

क्षमा करें, मैं सी ++/सीएलआई और सी # दोनों का उपयोग करता हूं और देर रात में मैंने * रेफरी * भाग के बजाय 'रेफस्ट्रक्चर 'के * स्ट्रक्चर * भाग पर ध्यान केंद्रित किया। मैं अपना जवाब ठीक कर दूंगा। –

+0

हाँ, '^ gcnew' बनाम' * gcnew' का उत्तर देने में थोड़ी देर लग गई, और '^' बनाम '' 'से'% 'बनाम' '' से अलग है। –

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