2011-12-08 9 views
5

Jestem nowy w Lua i chcę utworzyć tabelę [Doh], który będzie przechowywać wartości jak:Czy istnieje coś takiego jak wskaźniki w Lua?

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

Jednak najczęściej jest tylko jedno dziecko, więc łatwiej będzie uzyskać dostęp do wartości podobnego to:

parent.child.value 

Żeby było prościej, chciałbym przechowywać moje wartości, w taki sposób, że

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

Ale żeby to zrobić musiałbym zapisać tę wartość dwa razy w pamięć. Czy jest jakiś sposób mogę to zrobić tak, że:

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

bez zapisywania wartości dwukrotnie w pamięci?

Dodatkowe pytanie brzmi: jak sprawdzić, ile pamięci zajmuje tabela?

Odpowiedz

10

ale wartość zostanie zapisana jako ciąg, więc jest to ciąg znaków, który musi odwoływać się w obu miejscach, a nie tabeli.

pierwsze, wszystkie typy (oprócz logicznych, cyfr i lekkiego UserData) są referencje - jeśli t jest stół i zrobić t2 = t, wówczas zarówno t i t2 są odniesienia do tej samej tabeli w pamięci.

Druga sprawa - struna są internowane w Lua. Oznacza to, że wszystkie równe łańcuchy, takie jak "abc" i wynik "ab".."c", są w rzeczywistości pojedynczym ciągiem znaków. Lua przechowuje również tylko odniesienia do łańcuchów. Nie powinieneś więc martwić się pamięcią - istnieje tylko jedno wystąpienie ciągu na raz.

Możesz bezpiecznie wykonać parent.child.value = parent.child[1].value, użyjesz tylko pamięci do jednego gniazda w tabeli (kilka bajtów), żaden ciąg nie zostanie skopiowany, tylko odwołanie.

+0

niesamowite, wielkie dzięki. – Krystian

3

Tabele Lua (często używane jako obiekty) nie są kopiowane, ale są przywoływane. (wewnętrznie, wskaźnik służy do nich)

+0

ale wartość zostanie zapisana jako ciąg znaków, więc jest to ciąg, do którego należy się odwoływać w obu miejscach, a nie w tabeli. Czy twoja odpowiedź również jest ważna w tym przypadku? – Krystian

+0

Myślę, że tak. –

+0

teraz właściwym pytaniem będzie, jak sprawdzić rozmiar pamięci tabeli? W ten sposób na pewno odpowiemy na pytanie. – Krystian

3

Jest to ładny aplikacji dla korzystających metatables:

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

Jeśli indeks nie znajduje się w tabeli podrzędnej (jak „wartości”), to dostaje spojrzał w tabeli, która jest wartością __index z metatable (pierwszy element dziecka w tym przypadku).

Teraz jest problem z powyższego kodu, który możemy zobaczyć jak folows:

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

To dlatego, że metatable utrzymuje odniesienie do pierwszej tabeli podrzędnej, zapobiegając odnieść. Rozwiązaniem tego typu jest A) sprawienie, że metatable jest słabą tabelą, lub B) uczynienie pola __index funkcją, zamiast wskazywania go na tabelę.

-- 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. 

Jeśli jesteś naprawdę zainteresowany, aby przeczytać na metatables, spróbuj czytania Programming in Lua, chapter 13 i chapter 17 (weak tables).Lua-Users wiki on MetaMethods może być również interesujące.

+0

wielkie dzięki za to, że wygląda interesująco. Wciąż walczę z setmetatable i używając tabel jako obiektów w lua, ale dam mu szansę. Ta struktura, której zamierzam użyć, zostanie użyta tylko do odczytu i nie zostaną wprowadzone żadne modyfikacje, więc może ona faktycznie działać poprawnie. bardzo fajne, wielkie dzięki! – Krystian

0

Z tablicami C, parent.child i parent.child[0] są równoważne ze względu na arytmetykę wskaźnika. Naprawdę nie powinieneś próbować emulować jednej z najbardziej podatnych na błędy, mylących i zbędnych funkcji C tylko dlatego, że lubisz ten styl.

Powiązane problemy