Ruby';传递值';澄清
好的,所以Ruby是“按值传递”。但在Ruby中如何准确定义“按引用传递”和“按值传递”?我使用了这个答案,根据它,Ruby似乎是,嗯,一个混合体 从技术上讲,Ruby似乎是“按值传递”,不同的是,当您将值传递给方法时,该值不会被复制。如果我们定义“value”=对象,“reference”=指向该对象的引用变量,如果“passbyreference”等同于“passthereference”指向特定对象,那么“passbyreference”是否有意义?然后,一旦传递了“引用”,该方法就不会复制对象,而是实际拥有可以直接操作的原始对象本身(由变量引用)。如果我错了,请纠正我Ruby';传递值';澄清,ruby,Ruby,好的,所以Ruby是“按值传递”。但在Ruby中如何准确定义“按引用传递”和“按值传递”?我使用了这个答案,根据它,Ruby似乎是,嗯,一个混合体 从技术上讲,Ruby似乎是“按值传递”,不同的是,当您将值传递给方法时,该值不会被复制。如果我们定义“value”=对象,“reference”=指向该对象的引用变量,如果“passbyreference”等同于“passthereference”指向特定对象,那么“passbyreference”是否有意义?然后,一旦传递了“引用”,该方法就不会复
编辑:我知道这个问题,但不同的人似乎对传递引用/值有不同的定义。你可以在这个问题上说ruby是“传递引用值”的特例,但它没有抓住要点。只要把ruby中的所有东西都当作一个对象就行了
foo(14)传递对值为14的整数对象的引用。有一些事情是在幕后进行的,所以你最终不会得到14个对象中的100个,但从意图的角度来看,大多数时候你可以忘记这个概念。Ruby是按值传递的,就像C、Java、Python、Smalltalk、ECMAScript和其他许多东西一样。默认情况下,C++和C语言也通过值,必须使用特殊注释(C++中的代码>和代码> >代码> >代码>代码>,使用引用。< /P> 区别实际上相当简单:如果传递了引用,那么被调用方可以修改它,否则就不能。在Ruby中,被调用方不能修改引用,因为它是按值传递的:
def is_ruby_pass_by_value?(foo)
foo = 'No, Ruby is pass-by-reference.'
return nil
end
bar = 'Yes, of course, Ruby *is* pass-by-value!'
is_ruby_pass_by_value?(bar)
p bar
# 'Yes, of course, Ruby *is* pass-by-value!'
如您所见,在方法is\u ruby\u pass\u by\u value?
中,未传递引用条
/foo
,否则之后会看到修改<代码>条通过值传递,即传递的是条的内容(其中包含的值),而不是引用本身
现在,传递的值是什么?它不是字符串
对象。相反,它是指向字符串对象的指针。更准确地说:该指针的副本
现在,有两个指向字符串对象的指针。而且字符串
对象是可变的!因此,如果我跟随一个指针(foo
)并告诉String
对象改变它自己,然后我跟随另一个指针(bar
)并询问它的内容,那么我显然会看到改变的内容。这正是共享可变状态的本质,Ruby不是一种纯粹的功能性、引用透明的语言:
def is_ruby_pass_by_value?(foo)
foo.replace('More precisely, it is call-by-object-sharing!')
foo = 'No, Ruby is pass-by-reference.'
return nil
end
bar = 'Yes, of course, Ruby *is* pass-by-value!'
is_ruby_pass_by_value?(bar)
p bar
# 'More precisely, it is call-by-object-sharing!'
事实上,在Ruby中,由变量持有并作为参数传递的值始终是指针。几乎所有面向对象语言都是这样工作的。Barbara Liskov将这种传递值的特殊情况称为“按对象调用共享”,有时也称为“按共享调用”或“按对象调用”
但是,请注意,传递的值是指针这一事实与此完全无关。传递值与传递引用是关于参数是如何传递的,而不是参数是什么。C始终是按值传递,无论是传递int
还是指针。指针仍在按值传递。在Ruby中,指针也是按值传递的。Ruby和C之间的区别是a)在Ruby中只能传递指针,b)没有特殊语法指示传递指针
[注意:大多数Ruby实现实际上都会对直接传递小于指针的对象进行优化,而不是将指针传递给该对象。但是,它们只对语言规范保证为深度不可变的对象进行优化,因此不可能观察到它们之间的差异在传递指向该值的指针和直接传递该值之间。例如,对于Fixnum
s、Symbol
s、Float
s、nil
、true
和false
)
下面是C#中的一个示例,演示了传递值(即使该值是引用)和传递引用之间的差异:
class Program
{
static void IsCSharpPassByValue(string[] foo, ref string baz)
{
foo[0] = "More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value.";
foo = new string[] { "C# is not pass-by-reference." };
baz = "It also supports pass-by-reference if explicitly requested.";
}
static void Main(string[] args)
{
var quux = new string[] { "Yes, of course, C# *is* pass-by-value!" };
var grault = "This string will vanish because of pass-by-reference.";
IsCSharpPassByValue(quux, ref grault);
Console.WriteLine(quux[0]);
// More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value.
Console.WriteLine(grault);
// It also supports pass-by-reference if explicitly requested.
}
}
Ruby是“按引用传递”,区别如下:如果按引用传递,可能会对原始对象造成不良影响:
x = [ "virgin" ]
def do_bad_things_to( arg )
arg.clear << "bad things"
end
do_bad_things_to( x )
不可变对象(数字、符号、true
、false
、nil
…)人们常说,在Ruby中,它们是按值传递的,但事实上,这种区别对它们来说没有什么意义,就像在内存中保留它们内部的许多副本没有什么意义一样
更新:关于“引用”的含义,似乎存在术语上的争论。在Ruby中,Jörg Mittag的“通过引用传递”是通过关闭局部变量的闭包显式实现的:
baz = "Jörg"
define_method :pass_by_Jorgs_reference_to_baz do baz = "Boris" end
pass_by_Jorgs_reference_to_baz
baz #=> "Boris"
这不是一个重复的问题,我读过这个问题,不同的人对“参照传递”和“价值”似乎有不同的定义,这让我很困惑。顺便说一句,这个问题很好。哦,我现在看到它真的是一个重复的问题:-)@TonyHopkinson:我不认为这与纯粹主义、语言描述主义或任何其他类型的理论有任何关系-ism。这些是精确的科学术语,有精确的科学定义,Ruby要么符合定义(它对传递值适用),要么不符合定义(传递引用就是这样).C#在这里是一个很好的标准,因为它支持引用类型和值类型的按值传递和按引用传递。Ruby的行为与C#中引用类型的按值传递相同。所以,如果它的行为相同,为什么称它为不同呢
baz = "Jörg"
define_method :pass_by_Jorgs_reference_to_baz do baz = "Boris" end
pass_by_Jorgs_reference_to_baz
baz #=> "Boris"