मूल्य से स्विफ्ट पास या संदर्भ द्वारा पास है


100

मैं स्विफ्ट के लिए वास्तव में नया हूं और मैंने अभी पढ़ा है कि कक्षाओं को संदर्भ द्वारा पारित किया जाता है और सरणियों / तार आदि को कॉपी किया जाता है।

क्या संदर्भ द्वारा पास उसी तरह से है जैसे कि ऑब्जेक्टिव-सी या जावा जिसमें आप वास्तव में "ए" संदर्भ पास करते हैं या यह संदर्भ द्वारा उचित पास है?


"ऑब्जेक्टिव-पास या जावा के समान ही पास है" न तो ऑब्जेक्टिव-सी और न ही जावा में पास-बाय-रेफरेंस है।
23

2
हाँ। मुझे पता है। आप संदर्भ से नहीं गुजरते। आप संदर्भ को मान से पास करते हैं। मैंने मान लिया कि उत्तर देने के समय यह ज्ञात था।
gran_profaci

जावा मान से गुजरता है, संदर्भ से नहीं।
6rchid

जवाबों:


167

स्विफ्ट में चीजों के प्रकार

नियम है:

  • वर्ग उदाहरण संदर्भ प्रकार हैं (अर्थात एक वर्ग उदाहरण के लिए आपका संदर्भ प्रभावी रूप से एक सूचक है )

  • कार्य संदर्भ प्रकार हैं

  • बाकी सब कुछ एक मूल्य प्रकार है ; "बाकी सब कुछ" का अर्थ है केवल संरचना और उदाहरणों के उदाहरणों का उदाहरण, क्योंकि स्विफ्ट में यह सब है। उदाहरण के लिए, ऐरे और स्ट्रिंग्स संरचनात्मक उदाहरण हैं। आप उन चीजों में से एक का संदर्भ (एक फ़ंक्शन तर्क के रूप में) पते का उपयोग करके और पास कर सकते हैं inout, जैसा कि newacct ने बताया है। लेकिन प्रकार स्वयं एक मूल्य प्रकार है।

क्या संदर्भ प्रकार आप के लिए मतलब है

एक संदर्भ प्रकार की वस्तु व्यवहार में विशेष है क्योंकि:

  • कार्य करने या कार्य करने के लिए पास होने से एक ही वस्तु के कई संदर्भ मिल सकते हैं

  • ऑब्जेक्ट स्वयं भी उत्परिवर्तित है भले ही इसका संदर्भ एक स्थिर ( letया तो स्पष्ट या निहित) हो।

  • वस्तु का एक उत्परिवर्तन उस वस्तु को प्रभावित करता है जैसा कि सभी संदर्भों द्वारा देखा जाता है।

वे खतरे हो सकते हैं, इसलिए नज़र रखें। दूसरी ओर, एक संदर्भ प्रकार पास करना स्पष्ट रूप से कुशल है क्योंकि केवल एक पॉइंटर को कॉपी और पास किया जाता है, जो कि तुच्छ है।

क्या मूल्य प्रकार आप के लिए मतलब है

स्पष्ट रूप से, एक मान प्रकार पास करना "सुरक्षित" है, और letइसका अर्थ है कि यह कहता है: आप एक letसंदर्भ के माध्यम से एक संरचनात्मक उदाहरण या एनम उदाहरण को उत्परिवर्तित नहीं कर सकते । दूसरी ओर, उस मूल्य की एक अलग प्रतिलिपि बनाकर सुरक्षा प्राप्त की जाती है, है ना? क्या यह मूल्य प्रकार को संभावित रूप से महंगा बनाना नहीं है?

खैर, हाँ और नहीं। यह उतना बुरा नहीं है जितना आप सोच सकते हैं। जैसा कि नैट कुक ने कहा है, एक वैल्यू टाइप पास करना अनिवार्य रूप से कॉपी करने का नहीं है , क्योंकि let(स्पष्ट या निहित) अपरिवर्तनीयता की गारंटी देता है, इसलिए कुछ भी कॉपी करने की आवश्यकता नहीं है। और यहां तक ​​कि एक varसंदर्भ में गुजरने का मतलब यह नहीं है कि चीजों को कॉपी किया जाएगा , केवल यह कि वे आवश्यक हो सकते हैं (क्योंकि वहाँ एक उत्परिवर्तन है)। डॉक्स आपको विशेष रूप से सलाह देता है कि आप अपने घुटनों को मोड़ में न लें।


6
"कक्षा के उदाहरण संदर्भ द्वारा पारित किए जाते हैं। कार्य संदर्भ द्वारा पारित किए जाते हैं"। यह पास-दर-मूल्य है जब पैरामीटर inoutप्रकार का परवाह किए बिना नहीं होता है । चाहे कुछ पास-पास-संदर्भ हो, प्रकार के लिए ऑर्थोगोनल है।
newacct

4
@newacct खैर, निश्चित रूप से आप एक सख्त अर्थ में सही हैं! कड़ाई से, किसी को यह कहना चाहिए कि सब कुछ पास-बाय-वैल्यू है लेकिन यह माना जाता है कि एनम इंस्टेंस और स्ट्रक्चर इंस्टेंस वैल्यू टाइप हैं और क्लास इंस्टेंस और फंक्शन रेफरेंस टाइप हैं । देखें, उदाहरण के लिए, developer.apple.com/swift/blog/?id=10 - यह भी देखें developer.apple.com/library/ios/documentation/Swift/Conceptual/... हालांकि, मुझे लगता है कि मैं क्या सामान्य के साथ समझौते कहा शब्दों का अर्थ है।
मैट

6
राइट और वैल्यू टाइप / रेफरेंस टाइप को पास-बाय-वैल्यू / पास-बाय-रेफरेंस के साथ भ्रमित नहीं किया जाना चाहिए, क्योंकि वैल्यू टाइप को वैल्यू या रेफरेंस द्वारा पास किया जा सकता है, और रेफरेंस टाइप को वैल्यू या रेफरेंस से भी पास किया जा सकता है।
Newacct

1
@newacct बहुत उपयोगी चर्चा; मैं अपने सारांश को फिर से लिख रहा हूँ कि यह गुमराह न हो।
मैट

43

जब पैरामीटर नहीं होता है तो यह हमेशा पास-बाय-वैल्यू होता है inout

यदि पैरामीटर है तो यह हमेशा पास-बाय-संदर्भ होता है inout। हालांकि, यह कुछ हद तक जटिल है कि आपको पैरामीटर &को पास करते समय तर्क पर ऑपरेटर को स्पष्ट रूप से उपयोग करने की आवश्यकता होती है inout, इसलिए यह पास-बाय-संदर्भ की पारंपरिक परिभाषा को फिट नहीं कर सकता है, जहां आप चर को सीधे पास करते हैं।


3
यह जवाब, नैट कुक के साथ संयुक्त, मेरे लिए स्पष्ट था (C ++ से) इस तथ्य के इर्द-गिर्द कि "संदर्भ प्रकार" को भी फ़ंक्शन स्कोप के बाहर संशोधित नहीं किया जाएगा , जब तक कि आप इसे स्पष्ट रूप से निर्दिष्ट नहीं करते (उपयोग करके inout)
Gobe

10
inoutवास्तव में संदर्भ से पारित नहीं है, लेकिन कॉपी-इन-कॉपी यह केवल गारंटी देता है कि फ़ंक्शन कॉल के बाद संशोधित मूल्य मूल तर्क को सौंपा जाएगा। इन-आउट पैरामीटर्स
दलीजा प्रसनिकर

हालांकि यह सच है कि सब कुछ मूल्य से गुजरता है। संदर्भ प्रकार गुणों को उसी उदाहरण की प्रतिलिपि संदर्भ के रूप में फ़ंक्शन के अंदर संशोधित किया जा सकता है।
MrAn3

42

स्विफ्ट में सब कुछ डिफ़ॉल्ट रूप से "कॉपी" द्वारा पारित किया जाता है, इसलिए जब आप एक मूल्य-प्रकार पास करते हैं तो आपको मूल्य की एक प्रति मिलती है, और जब आप एक संदर्भ प्रकार पास करते हैं तो आपको संदर्भ की एक प्रति मिलती है, जिसका अर्थ है। (यही है, संदर्भ की प्रति अभी भी मूल संदर्भ के समान उदाहरण की ओर इशारा करती है।)

मैं ऊपर "कॉपी" के आसपास डरावने उद्धरण का उपयोग करता हूं क्योंकि स्विफ्ट बहुत अनुकूलन करता है; जहां तक ​​संभव हो, यह तब तक कॉपी नहीं होता जब तक कि उत्परिवर्तन या उत्परिवर्तन की संभावना नहीं होती। चूंकि पैरामीटर डिफ़ॉल्ट रूप से अपरिवर्तनीय हैं, इसका मतलब है कि अधिकांश समय वास्तव में कोई प्रतिलिपि नहीं होती है।


मेरे लिए यह सबसे अच्छा जवाब है क्योंकि यह स्पष्ट है कि उदाहरण के लिए गुणों को फ़ंक्शन के अंदर संशोधित किया जा सकता है यहां तक ​​कि पैरामीटर एक प्रति (मान द्वारा पास) है क्योंकि यह उसी संदर्भ को इंगित करता है।
MrAn3

9

यहाँ संदर्भ से गुजरने के लिए एक छोटा कोड नमूना है। ऐसा करने से बचें, जब तक कि आपके पास एक मजबूत कारण न हो।

func ComputeSomeValues(_ value1: inout String, _ value2: inout Int){
    value1 = "my great computation 1";
    value2 = 123456;
}

इसे इस तरह बुलाओ

var val1: String = "";
var val2: Int = -1;
ComputeSomeValues(&val1, &val2);

आपको ऐसा करने से क्यों बचना चाहिए?
बेवक़ूफ़

1
@Brainless क्योंकि यह कोड में अनावश्यक जटिलता जोड़ता है। इसमें पैरामीटर लेना और एकल परिणाम वापस करना सबसे अच्छा है। ऐसा करने के बाद, आमतौर पर खराब डिज़ाइन का संकेत मिलता है। इसे लगाने का एक और तरीका है कि संदर्भित चर में छिपे हुए साइड-इफेक्ट्स कॉल करने वाले के लिए पारदर्शी नहीं हैं।
क्रिस एमेलिंक्स

यह संदर्भ से नहीं गुजरता। inoutएक कॉपी है, कॉपी आउट ऑपरेटर। यह पहले ऑब्जेक्ट में कॉपी करेगा, फिर फ़ंक्शन रिटर्न के बाद मूल ऑब्जेक्ट को ओवरराइट कर देगा। जबकि यह समान लग सकता है, सूक्ष्म अंतर हैं।
हेंस हर्तेच

7

एप्पल स्विफ्ट डेवलपर ब्लॉग में एक पोस्ट में कहा जाता है मूल्य और संदर्भ के प्रकार है कि यह बहुत ही विषय पर एक स्पष्ट और विस्तृत चर्चा प्रदान करता है।

उद्धरण के लिए:

स्विफ्ट के प्रकार दो श्रेणियों में से एक में आते हैं: पहला, "मूल्य प्रकार", जहां प्रत्येक उदाहरण अपने डेटा की एक अनूठी प्रति रखता है, जिसे आमतौर पर एक संरचना, एनम या टुपल के रूप में परिभाषित किया जाता है। दूसरा, "संदर्भ प्रकार", जहां उदाहरण डेटा की एक प्रति साझा करते हैं, और प्रकार को आमतौर पर एक वर्ग के रूप में परिभाषित किया जाता है।

स्विफ्ट ब्लॉग पोस्ट में उदाहरणों के साथ मतभेदों की व्याख्या करना जारी है और पता चलता है कि आप कब एक का उपयोग करेंगे।


1
इस सवाल का जवाब नहीं है। प्रश्न पास-दर-मूल्य बनाम पास-दर-संदर्भ के बारे में है जो मूल्य प्रकार बनाम संदर्भ प्रकारों के लिए पूरी तरह से ऑर्थोगोनल है।
जोर्ज डब्ल्यू मित्तग

2

कक्षाएं संदर्भों द्वारा पारित की जाती हैं और दूसरों को डिफ़ॉल्ट रूप से मूल्य द्वारा पारित किया जाता है। आप inoutकीवर्ड का उपयोग करके संदर्भ से गुजर सकते हैं ।


यह गलत है। inoutएक कॉपी है, कॉपी आउट ऑपरेटर। यह पहले ऑब्जेक्ट में कॉपी करेगा, फिर फ़ंक्शन रिटर्न के बाद मूल ऑब्जेक्ट को ओवरराइट कर देगा। जबकि यह समान लग सकता है, सूक्ष्म अंतर हैं।
हेंस हर्टच

2

जब आप एक infix ऑपरेटर जैसे + = के साथ inout का उपयोग करते हैं, तो & पता प्रतीक को अनदेखा किया जा सकता है। मुझे लगता है कि संकलक संदर्भ से गुजरता है?

extension Dictionary {
    static func += (left: inout Dictionary, right: Dictionary) {
        for (key, value) in right {
            left[key] = value
        }
    }
}

ओरिजिनल + = newDictionaryToAdd

और अच्छी तरह से यह शब्दकोश 'जोड़' केवल एक मूल संदर्भ के लिए भी लिखता है, इसलिए लॉकिंग के लिए बहुत अच्छा है!


2

कक्षाएं और संरचनाएं

संरचनाओं और वर्गों के बीच सबसे महत्वपूर्ण अंतर यह है कि संरचनाओं को हमेशा तब कॉपी किया जाता है जब उन्हें आपके कोड में पास किया जाता है, लेकिन कक्षाओं को संदर्भ द्वारा पारित किया जाता है।

बंद

यदि आप किसी वर्ग आवृत्ति की संपत्ति को बंद करने का प्रावधान करते हैं, और वह बंद उदाहरण या उसके सदस्यों का उल्लेख करके उस आवृत्ति को कैप्चर करता है, तो आप बंद करने और आवृत्ति के बीच एक मजबूत संदर्भ चक्र बनाएंगे। स्विफ्ट इन मजबूत संदर्भ चक्रों को तोड़ने के लिए कैप्चर सूचियों का उपयोग करता है

एआरसी (स्वचालित संदर्भ गणना)

संदर्भ गिनती केवल कक्षाओं के उदाहरणों पर लागू होती है। संरचना और गणना मूल्य प्रकार हैं, संदर्भ प्रकार नहीं हैं, और संदर्भ द्वारा संग्रहीत और पारित नहीं किए जाते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.