Sid*_*Sid 245 ruby ruby-on-rails pass-by-reference
@user.update_languages(params[:language][:language1],
params[:language][:language2],
params[:language][:language3])
lang_errors = @user.errors
logger.debug "--------------------LANG_ERRORS----------101-------------"
+ lang_errors.full_messages.inspect
if params[:user]
@user.state = params[:user][:state]
success = success & @user.save
end
logger.debug "--------------------LANG_ERRORS-------------102----------"
+ lang_errors.full_messages.inspect
if lang_errors.full_messages.empty?
Run Code Online (Sandbox Code Playgroud)
@userobject会向方法中的lang_errors变量添加错误update_lanugages.当我对@user对象执行保存时,我丢失了最初存储在lang_errors变量中的错误.
虽然我试图做的更多是一个黑客(似乎没有工作).我想了解为什么变量值被淘汰了.我理解通过引用传递,所以我想知道如何在不被淘汰的情况下将该值保存在该变量中.
Abe*_*ker 417
其他的回答者都是正确的,但是一位朋友让我向他解释这个问题以及它真正归结为Ruby如何处理变量,所以我想我会分享一些我为他写的简单图片/解释(道歉的长度)并且可能有些过于简单化了):
str赋值为'foo'?时会发生什么?str = 'foo'
str.object_id # => 2000
Run Code Online (Sandbox Code Playgroud)

str创建了一个指向对象的标签,该标签'foo'对于此Ruby解释器的状态恰好位于内存位置2000.str使用=?将现有变量分配给新对象时会发生什么?str = 'bar'.tap{|b| puts "bar: #{b.object_id}"} # bar: 2002
str.object_id # => 2002
Run Code Online (Sandbox Code Playgroud)

str现在指向另一个对象.=来str?str2 = str
str2.object_id # => 2002
Run Code Online (Sandbox Code Playgroud)

str2被创建在指向同一个对象的str.str,并str2得到改变?str2.replace 'baz'
str2 # => 'baz'
str # => 'baz'
str.object_id # => 2002
str2.object_id # => 2002
Run Code Online (Sandbox Code Playgroud)

它与Q3/Q4中的情况基本相同; 该方法获取自己的变量/ label(str2)的私有副本,并将其传递给它(str).它不能更改标签str 指向的对象,但它可以更改它们都引用的对象的内容:
str = 'foo'
def mutate(str2)
puts "str2: #{str2.object_id}"
str2.replace 'bar'
str2 = 'baz'
puts "str2: #{str2.object_id}"
end
str.object_id # => 2004
mutate(str) # str2: 2004, str2: 2006
str # => "bar"
str.object_id # => 2004
Run Code Online (Sandbox Code Playgroud)
Chu*_*uck 238
在传统术语中,Ruby是严格按值传递的.但那不是你在这里问的那个.
Ruby没有任何纯粹的非引用值的概念,所以你当然不能将一个传递给一个方法.变量始终是对象的引用.为了获得一个不会从你下面改变的对象,你需要复制或克隆你传递的对象,从而给出一个没有其他人可以引用的对象.(尽管这不是防弹的 - 但两种标准克隆方法都做了浅拷贝,因此克隆的实例变量仍然指向与原件相同的对象.如果ivars引用的对象发生变异,那么仍然显示在副本中,因为它引用了相同的对象.)
Dav*_*cki 47
(使用Python的术语.)
要说Ruby使用"按值传递"或"按引用传递"并不具有足够的描述性,无法提供帮助.我认为,如今大多数人都知道,术语("价值"与"参考")来自C++.
在C++中,"按值传递"表示函数获取变量的副本,对副本的任何更改都不会更改原始变量.对于对象也是如此.如果按值传递对象变量,则会复制整个对象(包括其所有成员),并且对成员的任何更改都不会更改原始对象上的这些成员.(如果你按值传递一个指针却不同,但Ruby无论如何都没有指针,AFAIK.)
class A {
public:
int x;
};
void inc(A arg) {
arg.x++;
printf("in inc: %d\n", arg.x); // => 6
}
void inc(A* arg) {
arg->x++;
printf("in inc: %d\n", arg->x); // => 1
}
int main() {
A a;
a.x = 5;
inc(a);
printf("in main: %d\n", a.x); // => 5
A* b = new A;
b->x = 0;
inc(b);
printf("in main: %d\n", b->x); // => 1
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
in inc: 6
in main: 5
in inc: 1
in main: 1
Run Code Online (Sandbox Code Playgroud)
在C++中,"按引用传递"表示函数可以访问原始变量.它可以分配一个全新的文字整数,原始变量也将具有该值.
void replace(A &arg) {
A newA;
newA.x = 10;
arg = newA;
printf("in replace: %d\n", arg.x);
}
int main() {
A a;
a.x = 5;
replace(a);
printf("in main: %d\n", a.x);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
in replace: 10
in main: 10
Run Code Online (Sandbox Code Playgroud)
如果参数不是对象,Ruby使用pass by value(在C++意义上).但是在Ruby中,一切都是一个对象,所以在Ruby中C++意义上确实没有值得传递.
在Ruby中,使用"通过对象引用传递"(使用Python的术语):
因此,Ruby在C++意义上不使用"通过引用传递".如果是这样,那么将新对象分配给函数内的变量将导致在返回函数后忘记旧对象.
class A
attr_accessor :x
end
def inc(arg)
arg.x += 1
puts arg.x
end
def replace(arg)
arg = A.new
arg.x = 3
puts arg.x
end
a = A.new
a.x = 1
puts a.x # 1
inc a # 2
puts a.x # 2
replace a # 3
puts a.x # 2
puts ''
def inc_var(arg)
arg += 1
puts arg
end
b = 1 # Even integers are objects in Ruby
puts b # 1
inc_var b # 2
puts b # 1
Run Code Online (Sandbox Code Playgroud)
输出:
1
2
2
3
2
1
2
1
Run Code Online (Sandbox Code Playgroud)
*这就是为什么在Ruby中,如果要修改函数内部的对象但在函数返回时忘记这些更改,则必须在对副本进行临时更改之前显式创建对象的副本.
Jör*_*tag 45
Ruby通过引用或值传递吗?
Ruby是按值传递的.总是.没有例外.不,如果.没有但是.
这是一个简单的程序,它证明了这一事实:
def foo(bar)
bar = 'reference'
end
baz = 'value'
foo(baz)
puts "Ruby is pass-by-#{baz}"
# Ruby is pass-by-value
Run Code Online (Sandbox Code Playgroud)
Ari*_*Ari 19
Ruby是严格意义上的值传递,但值是引用.
这可以称为" 按值传递参考 ".这篇文章有我读过的最好的解释:http://robertheaton.com/2014/07/22/is-ruby-pass-by-reference-or-pass-by-value/
按值传递可以简要解释如下:
函数接收对(并将访问)内存中与调用者使用的相同对象的引用.但是,它不会收到调用者正在存储此对象的框; 在pass-value-by-value中,函数提供自己的框并为自己创建一个新变量.
由此产生的行为实际上是传递引用和传值的经典定义的组合.
Dom*_*ick 16
已经有了一些很好的答案,但我想发布关于这个主题的一对权威的定义,但也希望有人可以解释一下当局Matz(Ruby的创造者)和David Flanagan在他们出色的O'Reilly书中所说的内容,Ruby编程语言.
[来自3.8.1:对象引用]
将对象传递给Ruby中的方法时,它是传递给方法的对象引用.它不是对象本身,也不是对对象引用的引用.另一种说法是方法参数是通过值而不是通过引用传递的,但传递的值是对象引用.
由于对象引用传递给方法,因此方法可以使用这些引用来修改基础对象.当方法返回时,这些修改随后可见.
这一切对我来说都是有意义的,直到最后一段,尤其是最后一句.这充其量是误导性的,更糟糕的是混淆.无论如何,如何修改传递值的引用会改变底层对象?
Bre*_*red 15
Ruby通过引用或值传递吗?
Ruby是传递引用.总是.没有例外.不,如果.没有但是.
这是一个简单的程序,它证明了这一事实:
def foo(bar)
bar.object_id
end
baz = 'value'
puts "#{baz.object_id} Ruby is pass-by-reference #{foo(baz)} because object_id's (memory addresses) are always the same ;)"
Run Code Online (Sandbox Code Playgroud)
=> 2279146940 Ruby是传递引用2279146940,因为object_id(内存地址)始终相同;)
def bar(babar)
babar.replace("reference")
end
bar(baz)
puts "some people don't realize it's reference because local assignment can take precedence, but it's clearly pass-by-#{baz}"
Run Code Online (Sandbox Code Playgroud)
=>有些人没有意识到它的参考,因为本地分配可以优先,但它显然是通过参考传递
| 归档时间: |
|
| 查看次数: |
104630 次 |
| 最近记录: |