lua拷贝
首先要明白lua的引用类型
在 Lua 中,以下数据类型是引用类型:
- 表(table):Lua 的核心数据结构。
- 函数(function):闭包、函数均是引用类型。
- 线程(thread):Lua 协程(coroutine)。
- 用户数据(userdata):外部数据的引用。
对于这些引用类型的变量,赋值或传参时,实际传递的是地址引用,而不是数据的副本。
当对引用类型赋值时,新的对象指向的都是同一个地址
a = {a = 10 , b = 20}
a1 = a
a1.c = 30
print(a.c)
--输出30
在引用传递时引用类型作为参数传递在函数中修改值同时也会修改源数据
a = {a = 10 , b = 20}
function test(a2)
a2.d = 40
end
test(a)
print(a.d)
特殊的引用机制,弱引用表
local weaktable = {}
local strongtable = {}
--设置为弱引用表
setmetatable(weaktable,{__mode = 'kv'})
local a = {}
local b = {}
weaktable[a] = b
--strongtable[a] = b
a = nil
b = nil
collectgarbage()
for k,v in pairs(weaktable)
do
print(k,v)
end
--输出空 因为内存被回收了
-- for k,v in pairs(strongtable)
-- do
-- print(k,v)
-- end
local weaktable = {}
local strongtable = {}
--设置为弱引用表
setmetatable(weaktable,{__mode = 'kv'})
local a = {}
local b = {}
--weaktable[a] = b
strongtable[a] = b
a = nil
b = nil
collectgarbage()
-- for k,v in pairs(weaktable)
-- do
-- print(k,v)
-- end
for k,v in pairs(strongtable)
do
print(k,v)
end
--table: 0000000000e6b170 table: 0000000000e6b2b0
了解了引用现在正式开始lua拷贝的学习
由于lua中表是引用类型
当对表执行简单的拷贝时修改表的值会影响原表的值
在某些情境下这显然是我们不想看到的
function shallowCopy(original)
local copy = {}
for k, v in pairs(original) do
copy[k] = v
end
return copy
end
-- 示例
local t1 = {a = 1, b = {x = 10, y = 20}}
local t2 = shallowCopy(t1)
t2.a = 2
t2.b.x = 30
print(t1.a) -- 输出 1
print(t2.a) -- 输出 2
print(t1.b.x) -- 输出 30
print(t2.b.x) -- 输出 30
而在这个例子中t2是t1深拷贝,因此修改t2内容将不会影响到t1
function deepCopy(original)
local copy
if type(original) == "table" then
copy = {}
for k, v in pairs(original) do
copy[k] = deepCopy(v) -- 递归地拷贝每个元素
end
else
copy = original -- 对于非表类型,直接拷贝
end
return copy
end
-- 示例
local t1 = {a = 1, b = {x = 10, y = 20}}
local t2 = deepCopy(t1)
t2.a = 2
t2.b.x = 30
print(t1.a) -- 输出 1
print(t2.a) -- 输出 2
print(t1.b.x) -- 输出 10
print(t2.b.x) -- 输出 30
给一个很好的深拷贝实现
function deepCopy(original, seen)
seen = seen or {}
local copy
if type(original) == "table" then
if seen[original] then
return seen[original] -- 防止循环引用
end
copy = {}
seen[original] = copy
for k, v in pairs(original) do
copy[deepCopy(k, seen)] = deepCopy(v, seen) -- 递归拷贝键和值
end
else
copy = original -- 对于非表类型,直接拷贝
end
return copy
end