linux cp 深拷贝,Lua中常量的实现及表的深拷贝实现

lua中默认是没有c中的const常量的,在csdn上找到了一个使用setmetatable。主要原理就是重载__index方法(相当于get方法)和__newindex方法(相当于set方法)。但是他实现的是不支持表中有表的情况的。

下面是我修改后的代码:

function newConst( const_table )    --生成常量表功能

function Const( const_table )

local mt =

{

__index = function (t,k)

if type(const_table[k])=="table" then

const_table[k] = newConst(const_table[k])

end

return const_table[k]

end,

__newindex = function (t,k,v)

print("*can't update " .. tostring(const_table) .."[" .. tostring(k) .."] = " .. tostring(v))

end

}

return mt

end

local t = {}

setmetatable(t, Const(const_table))

return t

end

quan = {a = {[1]={2}}}

quan.b = quan

t = newConst(quan)

--t.b = 4

print(type(t))

print(quan.b)

for k,v in pairs(quan) do

print(k,v)

end

我也就是添加了6,7,8三行代码(刚开始想了半天以为递归了,结果思索了下,不是递归,只是函数的实现形式,调用newConst的次数就是读取表的深度,有环的表也不会出现问题的)。__index函数(看参数可以知道取元素t[k])拿到表的元素,如果元素是表则先将表常量化。__newindex函数(看参数可以知道写元素t[k]=v)是给元素赋值,这里不让它实现赋值操作,直接打印错误提示。

为什么要实现这个常量功能,因为现在的手游项目中使用了lua表存放数值策划表,往往程序写代码时会直接去读取静态数据表,万一不小心把表元素赋值了,那就是把静态数据改了,会导致游戏数据错误的。实现了这个lua常量就不会出现静态数据表被修改了。

但是如果需要复制一份静态数据,然后作为临时数据在游戏逻辑中处理(一个同事就这么用过。。。),把静态数据经过了常量处理就再也不能被修改了,不常量化也不行,中途被修改了就再也还原不了静态数据了。因此就需要实现lua表的深拷贝功能了(默然的表与表之间赋值只是简单的别名而已)。先说下思路吧,实现的效果是:

local B = deepcopy(A,n)

把A拷贝给B,n为拷贝深度。如果n为nil时那就是说要拷贝到底了,这又出现了中有环的问题了,不考虑环的问题可以很简单的递归实现,递归结束标识就是判断n的值。

先给上递归式的代码吧。

function table.deepcopy(object)

local lookup_table = {}

local function _copy(object)

if type(object) ~= "table" then

return object

elseif lookup_table[object] then

return lookup_table[object]

end

local new_table = {}

lookup_table[object] = new_table

for index, value in pairs(object) do

new_table[_copy(index)] = _copy(value)

end

return setmetatable(new_table, getmetatable(object))

end

return _copy(object)

end

为啥带环的table用这个函数不会无限递归呢?关键之处在于lookup_table,它记录了所有遍历过的table的副本(新的深拷贝的table),如果出现遍历过的直接返回那个副本。第12行为何有两个_copy,这里用的很巧妙,举个例子吧。

t = {

a = 1,

b = 2,

c = {

x = 1,

y = 2,

z = 3,

}

}

t[t.c] = t

t2 = table.deepcopy(t)

print(t2[t2.c])

如果index没有经过_copy处理,则打印出来的则是nil。为何经过_copy处理一定会是t2.c==t2呢?这也就是第6行判断的效果了,它返回的index就是t2.c(因为t2.c要么就是从第7行返回的,要没是新生成的副本,下次拷贝时还是取得同一个副本)。

接下来看第14行,这行不是我想要的,我的目的是拷贝出一份临时表,这分临时表要去除常量的特性,所以我修改如下

return setmetatable(new_table)

这样也就不保留常量特性了。

lua中使用局部函数的好处是很多的。look_up就用到了这个好处,如果lua不支持局部函数,那就只能将look_up表当做参数传递进去了。我之前实现了不支持环的版本,如下:

function table.deepcopy(t, n)

local newT = {}

if n == nil then    -- 默认为浅拷贝。。。

n = 1

end

for i,v in pairs(t) do

if n>0 and type(v) == "table" then

local T = table.deepcopy(v, n-1)

newT[i] = T

else

local x = v

newT[i] = x

end

end

return newT

end

非递归版本太牛逼了,不做介绍了自己想看源码的去看吧。

Lua 的详细介绍:请点这里

Lua 的下载地址:请点这里

推荐阅读:

0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值