Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Variables 函数/变量范围(传递值或参考?)_Variables_Scope_Lua - Fatal编程技术网

Variables 函数/变量范围(传递值或参考?)

Variables 函数/变量范围(传递值或参考?),variables,scope,lua,Variables,Scope,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? en

我完全被的变量作用域和函数参数传递(值或引用)搞糊涂了

请参阅下面的代码:

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) 
因此,这种行为完全使我困惑

  • 这是否意味着表变量 由传递给函数的 参考而非价值

  • 全局变量是如何创建的 与已定义的冲突 局部变量

    • 为什么
      modt
      能够 无法修改表
      moda
      要修改变量的值

Lua的
函数
用户数据
线程
(协同程序)类型通过引用传递。其他类型按值传递。或者像一些人喜欢说的那样;所有类型都按值传递,但
函数
用户数据
线程
都是引用类型

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

您猜对了,表变量是通过引用传递的。引用:

Lua中有八种基本类型:nil、boolean、number、string、function、userdata、thread和table。

表、函数、线程和(完整的)userdata值都是对象:变量实际上并不包含这些值,只包含对它们的引用。赋值、参数传递和函数返回总是操纵对这些值的引用;这些操作并不意味着任何类型的复制


所以nil、boolean、数字和字符串都是按值传递的。这正好解释了您观察到的行为。

我不会重复Bas Bossink和jA_cOp关于引用类型的回答,但是:

--因为它是定义局部的,所以不应该有func作用域

这是不正确的。Lua中的变量是,这意味着它们是在一个代码块及其所有嵌套块中定义的。
local
所做的是创建一个新变量,该变量仅限于语句所在的块,该块是函数体、“缩进级别”或文件

这意味着,无论何时引用变量,Lua都将“向上扫描”,直到找到一个代码块,其中该变量被声明为局部变量,如果没有这样的声明,则默认为全局范围

在这种情况下,
a
t
被声明为局部的,但声明在全局范围内,因此
a
t
是全局的;或者最多是当前文件的本地文件

然后,它们不会在函数内部被重新声明为
local
,而是被声明为参数,这具有相同的效果。如果不是函数参数,函数体内部的任何引用仍然会引用外部的变量

在lua-users.org上有一篇文章,其中有一些例子可能比我试图解释的更能帮助你。也是一本好书

这是否意味着表变量通过引用而不是值传递给函数

全局变量创建如何与已定义的局部变量冲突

事实并非如此。这可能是因为您有一个名为
t
的全局变量,并将其传递给一个名为
t
的参数的函数,但这两个
t
是不同的。如果将参数重命名为其他名称,例如,
q
,则输出将完全相同
modt(t)
只能修改全局变量
t
,因为您通过引用传递它。例如,如果调用
modt({})
,则全局
t
将不受影响

为什么modt能够修改表格,而moda却不能修改a变量


因为参数是局部的。将参数命名为
a
类似于使用
locala
声明局部变量,不同之处在于参数显然接收传入的值,而常规局部变量不接收。如果您的参数被称为
z
(或者根本不存在),那么
moda
确实会修改全局
a

jA_cOp说“所有类型都是按值传递的,但函数、表、用户数据和线程都是引用类型”是正确的

这与“表通过引用传递”之间的区别很重要

在这种情况下没有区别

function modt_1(x)
  x.foo = "bar"
end
结果:“通过引用传递表”和“通过值传递表,但表是引用类型”将执行相同的操作:x现在将其foo字段设置为“bar”

但对于这个功能来说,它是一个与众不同的世界

function modt_2(x)
  x = {}
end

在这种情况下,通过引用传递将导致参数更改为空表。但是,在“传递值,但它是引用类型”中,新表将在本地绑定到x,并且参数将保持不变。如果您在lua中尝试这一点,您会发现这是第二次发生(值是引用)。

这与按引用传递略有不同。(见我的答案)。特别是
函数(x)x={}end
的行为是不同的。一切都是按值传递的,某些类型(表、函数、线程和(完整的)用户数据值)是引用。这些引用是按值传递的。我发现一个很好的方法来考虑这一点,就是所有的东西都是按值传递的。然而,碰巧有些类型只是引用。引用本身是通过值传递的,这就是为什么您的示例不改变“t”。很好的解释:)