功能/变量范围通过值还是引用?

问题描述

| 我对Lua的变量作用域和函数参数传递(值或引用)完全感到困惑。 请参见下面的代码:
local a = 9        -- since it\'s define local,should not have func scope
local t = {4,6}    -- since it\'s define local,should not have func scope

function moda(a)
  a = 10           -- creates a global var?
end
function modt(t)
  t[1] = 7         -- create a global var?
  t[2] = 8
end

moda(a)
modt(t)
print(a)  -- print 9 (function does not modify the parent variable)
print(t[1]..t[2])  -- print 78 (some how modt is modifying the parent t var) 
因此,这种行为使我完全困惑。 这是否意味着表变量 被传递给函数 参考而不是价值? 全局变量如何创建 与已经定义的冲突 局部变量? 为什么“ 1”能 修改表格,但是
moda
不能 修改变量?     

解决方法

您猜对了,表变量是通过引用传递的。引用Lua 5.1参考手册:   Lua中有八种基本类型:nil,布尔值,数字,字符串,函数,userdata,线程和表。   ....      表,函数,线程和(完整)用户数据值是对象:变量实际上并不包含这些值,而只是对其的引用。赋值,参数传递和函数返回总是操纵对此类值的引用;这些操作并不意味着任何形式的复制。 因此,零,布尔值,数字和字符串按值传递。这正好解释了您观察到的行为。     ,Lua的
function
table
userdata
thread
(协程)类型通过引用传递。其他类型按值传递。或者像某些人喜欢的那样说;所有类型都按值传递,但
function
table
userdata
thread
是引用类型。
string
也是一种引用类型,但是是不变的,被嵌入和写时复制的-它的行为类似于值类型,但性能更好。 这是正在发生的事情:
local a = 9
local t = {4,6}

function moda(a)
  a = 10 -- sets \'a\',which is a local introduced in the parameter list
end

function modt(t)
  t[1] = 7 -- modifies the table referred to by the local \'t\' introduced in the parameter list
  t[2] = 8
end
也许这会使事物了解事物为什么如此:
local a = 9
local t = {4,6}

function moda()
  a = 10 -- modifies the upvalue \'a\'
end

function modt()
  t[1] = 7 -- modifies the table referred to by the upvalue \'t\'
  t[2] = 8
end

-- \'moda\' and \'modt\' are closures already containing \'a\' and \'t\',-- so we don\'t have to pass any parameters to modify those variables
moda()
modt()
print(a)  -- now print 10
print(t[1]..t[2])  -- still print 78
    ,当jA_cOp说“所有类型都通过值传递,但函数,表,用户数据和线程是引用类型”时,它是正确的。 此表与“通过引用传递表”之间的区别很重要。 在这种情况下,没有什么区别,
function modt_1(x)
  x.foo = \"bar\"
end
结果:“按引用传递表”和“按值传递表,但表是引用类型”都将执行相同的操作:x现在将其foo字段设置为“ bar”。 但是对于此功能,它却带来了与众不同的世界
function modt_2(x)
  x = {}
end
在这种情况下,按引用传递将导致参数更改为空表。但是,在“按值传递,但其引用类型为”中,新表将在本地绑定到x,并且参数将保持不变。如果在lua中尝试此操作,则会发现它是第二个(值是引用)。     ,我不会重复关于Bas Bossink和jA_cOp \关于引用类型的回答的内容,但是:   -由于是本地定义,因此不应具有func作用域 这是不正确的。 Lua中的变量具有词法范围,这意味着它们在代码块及其所有嵌套块中定义。 ѭ16所做的是创建一个新变量,该变量限于语句所在的块,该块可以是函数的主体,“缩进级别”或文件。 这意味着只要您引用一个变量,Lua就会“向上扫描”,直到找到其中该变量声明为局部的代码块为止,如果没有这样的声明,则默认为全局范围。 在这种情况下,
a
t
被声明为局部,但声明处于全局范围内,因此
a
t
是全局的;或最多只能是当前文件的本地文件。 这样就不会在函数内部将它们重新声明为“ 16”,而是将它们声明为参数,具有相同的效果。如果它们不是函数参数,则函数体内的任何引用仍将引用外部变量。 在lua-users.org上有一个“范围教程”,其中包含一些示例,这些示例可能会帮助您,而不是我尝试做的解释。在Lua的有关该主题的部分进行编程也是一本好书。     ,这是否意味着表变量是通过引用而不是值传递给函数的? 是。   全局变量创建如何与已经定义的局部变量冲突? 不是。之所以会这样显示,是因为您有一个名为
t
的全局变量,并将其传递给带有名为
t
的参数的函数,但是两个
t
是不同的。如果将参数重命名为其他名称,例如“ 25”,则输出将完全相同。
modt(t)
只能修改全局变量
t
,因为您要通过引用传递它。例如,如果您呼叫
modt({})
,则全局
t
将不受影响。   为什么modt可以修改表却moda不能修改变量? 因为参数是局部的。给参数
a
命名类似于使用
local a
声明局部变量,只是显然该参数会接收传入的值,而常规局部变量则不会。如果您的论点称为
z
(或根本不存在),那么
moda
确实会修改全局indeed17ѭ。     

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...