Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Variables 如何在Lua中获取表的实际副本?_Variables_Lua - Fatal编程技术网

Variables 如何在Lua中获取表的实际副本?

Variables 如何在Lua中获取表的实际副本?,variables,lua,Variables,Lua,因此,以下变量均指同一个表: x = {1,2,3} y=x z=y table.remove(z,3) 因此,以下代码将输出1,2 for k,v in pairs(x) do print(v) end 互联网只是指Lua总是通过引用而不是值来使用变量的能力 但有时我想操纵一个变量的副本,而不是原始变量。怎么做?为什么Lua使真正通过值而不仅仅是引用复制变量变得如此困难 为什么Lua使真正通过值而不仅仅是引用复制变量变得如此困难 因为“复制”一张表的意义很大程度上取决于该表中的内容

因此,以下变量均指同一个表:

x = {1,2,3}
y=x
z=y
table.remove(z,3)
因此,以下代码将输出1,2

for k,v in pairs(x) do
    print(v)
end
互联网只是指Lua总是通过引用而不是值来使用变量的能力

但有时我想操纵一个变量的副本,而不是原始变量。怎么做?为什么Lua使真正通过值而不仅仅是引用复制变量变得如此困难

为什么Lua使真正通过值而不仅仅是引用复制变量变得如此困难

因为“复制”一张表的意义很大程度上取决于该表中的内容

首先,一些术语。您没有引用“变量”;您正在获取一个表的引用。“变量”只是一些东西的持有者,比如数字、字符串或对表的引用

所以当你说“真正地复制一个变量”时,你实际上的意思是“复制一个表”。。。这不容易

考虑下表:

local tbl = {x = 5, y = {20}}
如果要复制该表,是否希望新表的
y
字段具有旧表存储的表的副本?或者您希望该表本身是原始表的副本

两个答案都不对;你想要哪一个完全取决于你想做什么。但您不能盲目地进行表的递归复制,因为:

local tbl = {x = 5, y = {20}}
tbl._tbl = tbl
此表现在存储对自身的引用。尝试对该表进行盲递归复制将导致无限递归。您必须检测表引用自身,从而使新表存储对新表的引用。它变得更加复杂:

local tbl = {x = 5, y = {20}}
tbl.z = tbl.y
此表现在有两个引用同一表的字段。如果您想获得该表的真实副本,那么副本需要认识到两个字段相互引用,以便在复制第一个字段时,第二个字段可以引用新副本,而不是再次复制它

我甚至还没有进入元表和你能接触到的体操。这也不包括对基本上不可复制的事物的讨论,比如来自基于C的API的userdata对象。如果我将
io.open
的结果存储在表中,则没有复制该文件句柄的机制。那么,您的复制例程应该做什么呢


Lua没有默认的表复制API,以确保您自己能够花时间了解复制算法需要有多复杂。

只需将值分配给新变量,就可以复制数字或字符串。另一方面,桌子需要更多的工作

要在lua中复制表,需要定义一个复制函数。 两种常见的复制函数类型是浅复制和深复制

浅拷贝

这是一个简单、幼稚的实现。它只复制顶级值及其直接子级;不需要处理更深层次的子级、元表或特殊类型,如用户数据或协同路由。它也容易受到_配对元方法的影响

深度复制

深度副本复制所有级别(或级别的特定子集)。 下面是一个简单的递归实现,它额外处理元表并避免_对元方法


正如Nicol Bolas所说,复制表有很多陷阱。 在另一个SO问题中,给出了以下示例,该示例确实涵盖了一些令人关注的案例,例如:

  • 表作为键
  • 保持元表
  • 递归表
泰勒的例子:

function copy(obj, seen)
    if type(obj) ~= 'table' then
        return obj 
    end
    if seen and seen[obj] then
        return seen[obj] 
    end
    local s = seen or {}
    local res = setmetatable({}, getmetatable(obj))
    s[obj] = res
    for k, v in pairs(obj) do 
        res[copy(k, s)] = copy(v, s) 
    end
    return res
end
这些函数中的每一个都有不同的用例,如果您使用像
x={1,2,3}
这样的浅表,您可以做一些简单的事情:

x = {1,2,3}
y = {table.unpack(x)}
function copy(obj, seen)
    if type(obj) ~= 'table' then
        return obj 
    end
    if seen and seen[obj] then
        return seen[obj] 
    end
    local s = seen or {}
    local res = setmetatable({}, getmetatable(obj))
    s[obj] = res
    for k, v in pairs(obj) do 
        res[copy(k, s)] = copy(v, s) 
    end
    return res
end
x = {1,2,3}
y = {table.unpack(x)}