2011-12-08 21 views
5

Soy nuevo en Lua y quiero crear una tabla [do] que almacenar valores como:¿Hay algo así como indicadores en Lua?

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

, más a menudo sólo hay un niño, por lo que sería más fácil para acceder al valor igual esto:

parent.child.value 

para simplificar las cosas, me gustaría guardar mis valores, de una manera, que

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

pero para ello tendría que almacenar este valor dos veces en la memoria. ¿Hay alguna manera de que pudiera hacerlo, de modo que:

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

sin almacenar el valor de dos veces en la memoria?

La pregunta adicional es, ¿cómo comprobar cuánta memoria ocupa una mesa?

Respuesta

10

pero el valor se almacena en forma de cadena, por lo que es una cadena que tiene que ser referencia en ambos lugares, y no de mesa.

En primer lugar, todos los tipos (excepto booleanos, números y los datos de usuario de luz) son referencias - si t es una tabla y que hacen t2 = t, entonces ambos t y t2 son referencias a la misma mesa en la memoria.

Segunda cosa - cadena están internados en Lua. Eso significa que todas las cadenas iguales, como "abc" y el resultado de "ab".."c" son en realidad una sola cadena. Lua también almacena solo referencias a cadenas. Por lo tanto, no debe preocuparse por la memoria: solo hay una instancia de la cadena a la vez.

Puede hacer con seguridad parent.child.value = parent.child[1].value, solo usará una memoria para una ranura en una tabla (unos pocos bytes), no se copiará ninguna cadena, solo se hace referencia a ella.

+0

impresionante, muchas gracias. – Krystian

3

Las tablas Lua (a menudo se usan como objetos) no se copian, sino que se hace referencia a ellas. (internamente, un puntero se utiliza para ellos)

+0

pero el valor se almacenará como una cadena, por lo que es una cadena a la que se debe hacer referencia en ambos lugares, no en la tabla. ¿Tu respuesta también es válida en este caso? – Krystian

+0

Creo que sí. –

+0

ahora la pregunta correcta sería cómo verificar el tamaño de la memoria de una tabla? De esta manera, podremos responder la pregunta con seguridad. – Krystian

3

Esta es una buena aplicación para el uso de metatablas:

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

Si no se encuentra un índice en la tabla secundaria (como 'valor'), que se busca en la tabla que es el valor de __index de el metatable (el primer elemento del niño en este caso).

Ahora hay un problema con el código encima de la cual podemos ver como folows:

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

Esto se debe a la metatabla mantiene una referencia a la primera tabla secundaria, evitando que pueda ser cosechado. La solución para este tipo de cosas es A) hacer que el metatable sea una tabla débil, o B) hacer que el campo __index sea una función, en lugar de hacer referencia a una tabla.

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

Si usted está realmente interesado en leer sobre metatablas, trata de leer Programming in Lua, chapter 13 y chapter 17 (weak tables).Lua-Users wiki on MetaMethods también podría ser interesante.

+0

muchas gracias por esto, parece interesante. Todavía estoy luchando con el setmetatable y el uso de tablas como objetos en lua, pero le daré una oportunidad. Esta estructura que voy a utilizar se utilizará solo como lectura y no se realizarán modificaciones, por lo que en realidad podría funcionar bien. muy bueno, muchas gracias! – Krystian

0

Con matrices C, parent.child y parent.child[0] son equivalentes debido a la aritmética del puntero. Realmente no deberías tratar de emular una de las funciones más propensas a errores, confusas y redundantes de C simplemente porque te gusta el estilo.

Cuestiones relacionadas