2011-12-08 15 views
5

मैं लुआ के लिए नया हूँ और मैं एक मेज [DOH] जो की तरह मान संग्रहीत हैं बनाना चाहते हैं:क्या लुआ में पॉइंटर्स की तरह कुछ भी है?

parent.child[1].value = "whaterver" 
parent.child[2].value = "blah" 

हालांकि, सबसे अधिक बार वहाँ केवल एक ही बच्चा है, तो ऐसा लगता है कि मूल्य का उपयोग करने के आसान होगा इस:

parent.child.value 

बातें सरल, मुझे इस तरह से मेरी मान संग्रहीत करना चाहते हैं बनाने के लिए,

parent.child[1].value == parent.child.value 

लेकिन यह करने के लिए है कि मैं दो बार में यह मान संग्रहीत करने के लिए होगा यादाश्त। वहाँ किसी भी तरह से मैं यह कर सकता है, ताकि:

parent.child.value points to parent.child[1].value 

मूल्य स्मृति में दो बार भंडारण के बिना?

अतिरिक्त प्रश्न यह है कि तालिका को कितनी मेमोरी लेती है यह जांचने के लिए?

उत्तर

10

लेकिन मूल्य स्ट्रिंग के रूप में संग्रहीत किया जाएगा, तो यह एक स्ट्रिंग है करने की जरूरत है दोनों स्थानों पर, नहीं तालिका में संदर्भित किया जा रहा है।

सबसे पहले, सभी प्रकार के (बूलियन्स, संख्या और प्रकाश userdata को छोड़कर) संदर्भ हैं - अगर t एक टेबल है और आप t2 = t करते हैं, तो दोनों t और t2 स्मृति में एक ही मेज के लिए संदर्भ।

दूसरी बात - स्ट्रिंग को लुआ में प्रशिक्षित किया जाता है। इसका मतलब है कि सभी बराबर तार, जैसे "abc" और "ab".."c" का परिणाम वास्तव में एक स्ट्रिंग है। लुआ तारों के केवल संदर्भों को भी स्टोर करता है। इसलिए आपको स्मृति के बारे में चिंता नहीं करनी चाहिए - एक समय में स्ट्रिंग का केवल एक ही उदाहरण है।

आप सुरक्षित रूप से parent.child.value = parent.child[1].value कर सकते हैं, आप केवल एक टेबल (कुछ बाइट्स) में एक स्लॉट के लिए मेमोरी का उपयोग करेंगे, कोई स्ट्रिंग कॉपी नहीं की जाएगी, केवल संदर्भित किया जाएगा।

+0

कमाल, बहुत बहुत धन्यवाद। – Krystian

3

लुआ टेबल (अक्सर वस्तुओं के रूप में उपयोग किया जाता है) की प्रतिलिपि नहीं बनाई जाती है, लेकिन संदर्भित किया जाता है। (आंतरिक रूप से, एक सूचक उन्हें प्रयोग किया जाता है)

+0

लेकिन मान स्ट्रिंग के रूप में संग्रहीत किया जाएगा, इसलिए यह एक स्ट्रिंग है जिसे दोनों जगहों पर संदर्भित करने की आवश्यकता है, तालिका में नहीं। क्या आपका उत्तर इस मामले में भी मान्य है? – Krystian

+0

मुझे लगता है कि हाँ। –

+0

अब उचित प्रश्न यह होगा कि तालिका के मेमोरी आकार को कैसे जांचें? इस तरह हम निश्चित रूप से प्रश्न का उत्तर देने में सक्षम होंगे। – Krystian

3

यह metatables प्रयोग करने के लिए एक अच्छा अनुप्रयोग है:

parent={ 
    child={ 
     {value="whatever"}, 
     {value="blah"} 
    } 
} 
setmetatable(parent.child,{__index=parent.child[1]}) 

एक सूचकांक बच्चे तालिका में नहीं मिला है, तो ('मूल्य' की तरह), यह तालिका के __index का मूल्य है कि में देखा जाता है मेटाटेबल (इस मामले में बच्चे का पहला तत्व)।

print(parent.child.value) -- prints whatever 
parent.child[1]=nil --remove first child 
print(parent.child.value) -- still prints whatever! 

इसका कारण यह है metatable पहले बच्चे मेज के लिए एक संदर्भ रहता है, काटा जा रहा से रोकता है:

अब उपरोक्त कोड के साथ एक समस्या है जो हम folows के रूप में देख सकते हैं। इस तरह की चीजों के लिए कामकाज ए है) मेटाटेबल को कमजोर टेबल बनाते हैं, या बी) __index फ़ील्ड को एक टेबल पर संदर्भित करने के बजाय एक फ़ंक्शन बनाते हैं।

-- A) 
setmetatable(parent.child, setmetatable(
    {__index=parent.child[1]} -- metatable for the child table 
    {__mode='v'}-- metatable for the metatable, making it have weak keys 
    ) 
) 
parent.child[1]=nil 
print(parent.child.value) --returns nil 
parent.child[1]={value='foo'} 
print(parent.child.value) -- prints nil, the metatable references to a non-existant table. 
-- hence solution B) 

setmetatable(parent.child, {__index=function(t,k) return parent.child[1][k]}) 
print(parent.child.value) -- 'whatever' 
parent.child[1]=nil 
print(parent.child.value) -- nil 
parent.child[1]={value='foobar' 
print(parent.child.value) -- foobar, now it will always refer to the table at child[1], even when it changes. 

तुम सच में metatables पर पढ़ने के लिए रुचि रखते हैं, Programming in Lua, chapter 13 और chapter 17 (weak tables) पढ़ने की कोशिश।Lua-Users wiki on MetaMethods भी दिलचस्प हो सकता है।

+0

इसके लिए बहुत बहुत धन्यवाद यह दिलचस्प लग रहा है। मैं अभी भी सेटमेटेबल के साथ संघर्ष कर रहा हूं और लुआ में ऑब्जेक्ट्स के रूप में टेबल का उपयोग कर रहा हूं, लेकिन मैं इसे एक शॉट दूंगा। मैं जिस संरचना का उपयोग करने जा रहा हूं वह केवल पढ़ने के लिए उपयोग किया जा रहा है और कोई संशोधन नहीं किया जाएगा, इसलिए यह वास्तव में ठीक काम कर सकता है। बहुत अच्छा, बहुत बहुत धन्यवाद! – Krystian

0

सी सरणी के साथ, parent.child और parent.child[0] पॉइंटर अंकगणित के बराबर हैं। आपको वास्तव में सी की सबसे त्रुटि-प्रवण, भ्रमित और अनावश्यक सुविधाओं में से एक को अनुकरण करने की कोशिश नहीं करनी चाहिए क्योंकि आपको शैली पसंद है।

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