浅拷贝
Lua语言基础数据类型的拷贝采用值传递的方式;table类型变量的拷贝采用弱引用的方式,像C++语言中的引用传参数。1
2
3
4
5local a = {1, 2}
local b = a
print(a) -->table: 0x82b080
print(b) -->table: 0x82b080
可以看到a,b 指向了同一个内存地址,即指向了同一个元素。
深度拷贝
这种弱引用的赋值方式有利有弊,那么如果我们想对一个变量进行深度拷贝(deep copy)呢,就需要自己手动实现:
方法1
1 | function copy1(obj) |
这种方法将深度拷贝的思想表现出来了,采用递归的方式逐层拷贝数据类型。普通元素直接赋值,table类型元素拆开后每个元素分别处理。
但这个算法有两种情况没考虑到:
- 元表的继承
- 当元素的table引用存在嵌套
方法2
继承元表1
2
3
4
5
6
7
8
9
10
11
12
13function copy2(obj)
if type(obj) ~= 'table' then
return obj
end
local res = setmetatable({}, getmetatable(obj)) -- (新加)继承元表
for k, v in pairs(obj) do
res[copy2(k)] = copy2(v)
end
return res
end
方法3
处理引用嵌套的问题1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23function copy3(obj, seen)
-- Handle non-tables and previously-seen tables.
if type(obj) ~= 'table' then
return obj
end
if seen and seen[obj] then
return seen[obj]
end
-- New table; mark it as seen an copy recursively.
local s = seen or {}
local res = setmetatable({}, getmetatable(obj))
s[obj] = res
for k, v in pairs(obj) do
res[copy3(k, s)] = copy3(v, s)
end
return res
end
-- 其中seen为table,与其相关的代码负责处理递归引用的情况。
以上代码引用自:How to deep copy Lua values
感谢作者!