6

Lua优化——认识局部变量中的常见陷阱

 3 years ago
source link: https://blog.uwa4d.com/archives/UWA_Pipeline38.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

在上期《Lua优化:破解全局变量的使用困局》中,我们以UWA本地资源检测内相关的规则为依托,针对全局变量为大家介绍了在Lua中多种需要关注的使用场景,并结合简单的代码示例进行了直观说明。

本期我们将从“局部变量”入手,来分析Lua使用时可能发生的各种不合理情况。我们依然会以简单的例子来帮助大家读懂这些规则,力图以浅显易懂的表达,让职场新手或优化萌新能够深入理解。


在Lua中,我们会频繁使用到局部变量,但编写时代码的不规范或者逻辑上的疏忽,往往会导致变量未被正确应用:比如相关的变量或者值没有被正确使用和参与运算;又或者某些变量或者值被覆盖。这些不正确、不规范的代码使用就很有可能导致无法预知的错误和资源上的浪费。接下来我们进行具体分析。

1、局部变量相关

1.1 未被使用的局部变量

1.png
例如,声明了一个局部变量bar:
local bar=5

但之后再没有使用过局部变量bar。

1.2 未被使用的参数变量

2.png
在如下代码中:
function fun(x,y)
    print(x)
end

函数fun有两个参数x,y。但参数y从未被使用过。

1.3 未被使用的循环变量

3.png
在如下代码中:
for i=1,100 do
    print("huh")
end

局部变量i从未被使用过。

上述三条规则,都表示代码中有从未被使用的局部变量。

1.4 访问了一个未被设置的局部变量

4.png
在如下代码中:
local num
print(num.string)

局部变量num还未被赋值就被访问了,num还是一个nil,这样会造成错误。

1.5 设置了一个局部变量,但从未被访问

5.png
在如下代码中:
local num=5
num=6

局部变量num有被赋值的操作,但从未被使用过。

1.6 设置了一个参数变量,但从未被访问

6.png
在如下代码中:
function fun(num)
    num=6
end

参数num有被赋值的操作,但从未被使用过。

1.7 设置了一个循环变量,但从未被访问

7.png
在如下代码中:
for i=1,100 do
    i=2
end

循环变量i有被赋值的操作,但从未被使用过。

上述三条规则,都表示代码中有局部变量被赋值的操作,但从未被使用过。

1.8 更改了一个局部变量,但从未被访问

8.png
在如下代码中:
local bar={"aaa"}
bar.dd='ff'

局部变量bar的域“dd”被赋值为“ff”,但局部变量bar从未被使用过。表示代码中有局部变量的域发生改变的操作,但该局部变量从未被使用过。


2、值相关

2.1 未被使用的一个局部变量的值

9.png
在如下代码中:
local o = 5
print(o)
o=6

局部变量o的值被修改为6之后,再未被使用过。

2.2 未被使用的一个参数变量的值

10.png
在如下代码中:
function fun(x)
    x=3
    print(x)
end

参数x被赋值为3,然后被使用(输出)。但参数x初始值从未被使用。

2.3 未被使用的一个循环变量的值

11.png
在如下代码中:
for index=1,100 do
    index=2
    print(index)
end

循环变量index被赋值为2,然后被使用(输出)。但循环变量index的初始值从未被使用。

2.4 未被使用的一个表文字域的值

12.png
在如下代码中:
local bar = {b = 1, b = 2}

表bar中的Key为“b”的值被覆盖。

2.5 访问未被初始化的局部变量

13.png
在如下代码中:
local bar
if condition() 
    bar={}
else
    print(bar)

else分支语句中,访问了bar这个未初始化的局部变量。

2.6 更改了一个局部变量的值,但从未被访问

14.png
在如下代码中:
local function fun(st)
    if not st then
        st = {}
    end
    st.aa=2
end

local num
fun(num)
print(num)
>nil

程序原本试图当参数st为nil的时候初始化st为一个table,然后赋值。但实际上类似于值传递,参数st依然是nil,即局部变量num依然是nil。所以第三行的参数st初始化的值,从未被访问过。

2.7 更改了一个未被初始化的局部变量

15.png
在如下代码中:
local bar
bar.a=2
bar={}

局部变量b在第三行进行初始化操作,而第二行还未初始化的局部变量b进行了修改。


3、与覆盖行为相关

3.1 重定义了一个局部变量

16.png
在如下代码中:
local bar={}
local bar={"huh"}

局部变量bar被重定义。

3.2 重定义了一个参数变量

17.png
在如下代码中:
function fun(bar)
    local bar={}
end

局部变量“bar”和参数“bar”同名。

3.3 重定义了一个循环变量

18.png
在如下代码中:
for i=1,100 do 
    local i={}
end

循环变量“i”和局部变量“i”同名。

3.4 覆盖了一个局部变量

19.png
在如下代码中:
local bar
for i=1,100 do
    local bar={}
end

在循环语句这段作用域内定义了一个局部变量“bar”,覆盖了作用域外的同名局部变量“bar”。

3.5 覆盖了一个参数变量

20.png
在如下代码中:
function fun(x)
    if condition() then
        local x={}
        print(x)
    else
        print(x)
    end
end

在if分支的作用域中,局部变量x覆盖了同名参数x。

3.6 覆盖了一个循环变量

21.png
在如下代码中:
for i=1,100 do
    if condition() then
        local i={"huh"}
        print(i)
    else
        print(i)
end

在if分支的作用域中,局部变量x覆盖了同名循环变量x。

3.7 覆盖了一个上值

22.png

在如下代码中:

local bar
function fun()
    local bar={}
end

在函数fun的作用域中,局部变量“bar”覆盖了同名上值“bar”。

3.8 覆盖了一个上值参数

23.png
在如下代码中:
function fun(bar)
    local function fun2()
        local bar={}
    end
    return fun2
end

在fun2函数作用域中,局部变量“bar”覆盖了同名上值参数“bar”。

3.9 覆盖了一个上值循环变量

24.png
在如下代码中:
for index=1,100 do
    local function fun()
        local index={}
    end
end

在函数fun作用域中,局部变量“index”覆盖了同名上值循环参数“index”。


希望以上这些简单的示例能在实际的开发过程中为大家带来帮助,从而最大程度上避开这些在使用Lua时会遇到的问题。同时,也欢迎大家来使用UWA推出的本地资源检测服务,可帮助大家尽早对项目建立科学的检测规范。

25.png

万行代码屹立不倒,全靠基础掌握得好!

《场景检测:面片、光影和物理属性》
《场景检测:Audio Listener、RigidBody和Prefab连接》
《场景检测:雾效、Canvas和碰撞体》
《特效优化2:效果与性能的博弈》
《特效优化:发现绚丽背后的质朴》
《Prefab优化:预制体中的各种细节选择》

性能黑榜相关阅读

《那些年给性能埋过的坑,你跳了吗?》
《那些年给性能埋过的坑,你跳了吗?(第二弹)》
《掌握了这些规则,你已经战胜了80%的对手!》


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK