我对ruby还是很陌生,但来自C / C ++背景,我相信我对计算机和编程的工作原理有基本的了解。
在C ++中,如果您要创建一个指向值的指针,则可以将其指定为指针:http://www.cplusplus.com/doc/tutorial/pointers/。
示例:
int x = 3;
int *p = &x;
*p = 4;
std::cout << x;
这对我来说很有意义,因为现在P
指向X
的地址,因此,当我们更改P
的值时,X
也将更改。 X
在这种情况下将输出4。
但是当我跑步时:
a = []
b = a
a[0] = 3
p b
# => [3]
c = "this is a string"
d = c
c.upcase!
c = "the string has been edited"
p d
# => THIS IS A STRING
在红宝石中,b
输出[3]
,对我来说应该什么也不输出。 d
输出"THIS IS A STRING"
而不是"the string has been edited"
。 Ruby and pointers是另一个问题,他们将探讨如何在ruby中使用指针。
我的问题是:为什么数组在ruby中被视为指针,它如何工作? b
是否像C ++那样指向a
的地址?是什么使变量更改其指向的内容?例如:如果a = b
何时a != b
?为什么整数不指向另一个变量的地址?
答案 0 :(得分:4)
为什么数组被视为ruby中的指针,它如何工作?
不是。 Ruby中没有“指针”之类的东西。
b
是否像C ++那样指向a
的地址?
在Ruby中没有“地址”之类的东西。语言规范说,当您取消引用变量时,它将评估分配给该变量的最后一个对象。 如何语言实现完全无关紧要,您不应该,实际上不知道。它可以使用指向内存位置的指针。它可以使用字典。它可以将这些价值打印在纸上,然后传真到东亚的一家血汗工厂,由儿童奴隶解释。 (那将是非常不道德,不道德和违法的,但这将是一个完全有效的实现。)
是什么使变量更改其指向的内容?
赋值和 only 赋值可以更改变量的绑定。
例如:如果
a = b
何时a != b
?
当!=
方法被覆盖时可以这样说。那将是一个可怕的主意,但是:
class Foo
def !=(*)
false
end
end
a = Foo.new
b = a
a != b #=> false
为什么整数不指向另一个变量的地址?
同样,在Ruby中没有“指针”或“地址”之类的东西,因此,整数永远不能“指向”“地址”,这仅仅是因为“指向”和“地址”不是概念在Ruby中存在。
让我们逐行浏览代码:
a = []
您创建一个新的Array
对象,并将本地变量a
绑定到该新数组对象。
b = a
现在,您将绑定本地变量b
与计算表达式a
的结果。评估仅包含变量名称的表达式的结果是什么?变量被取消引用,即,它求值的对象早先与变量绑定。
在这种情况下,该对象是您在第1行上创建的Array
。
a[0] = 3
此行仅是以下行的语法糖:
a.[]=(0, 3)
在这里,您正在发送消息[]=
,该消息将两个参数0
和3
传递给取消引用局部变量a
的结果。再次,取消引用局部变量a
的结果是变量绑定到的最后一个变量,即第1行的Array
。方法Array#[]=
被定义为对其接收方进行变异,以便放置它的第二个参数位于第一个参数指定的索引处。
该方法不必 对其接收者进行变异。它还可以返回Array
的更新的副本。 (尽管在这种特殊情况下,这是没有用的,因为a[0] = 3
语法糖的行为类似于赋值,因此总是在右边求值。换句话说,Array#[]=
的返回值将被忽略。除非您使用显式方法调用语法a.[]=(0, 3)
。)
p b
在这里,我们再次取消引用局部变量b
,该变量仍指向完全相同的对象(从来没有进行任何重新分配),它仍然是第1行的Array
。 >
整个代码中只有一个Array
。您从未创建第二个,也从未调用过将返回新Array
的方法。
与更改接收者相对的一种方法是做返回新的Array
是方法Array#+
。这是使用Array#+
的替代示例:
a = []
b = a
a += [3]
a += [3]
等效于a = a + [3]
,等效于a = a.+([3])
。因此,我们取消引用a
,它从第1行得到Array
,然后我们向它发送带有单个参数+
的消息[3]
。 Array#+
被定义为返回一个新的Array
,它是接收者和参数的串联。最后,我们将此新的Array
分配给局部变量a
。
p b
局部变量b
仍绑定到同一对象,因为我们从未重新分配它。因此,它仍然绑定到第1行的Array
上。我们从未更改过此Array
,因此,打印的是[]
。
关于第二个示例(这次我走得更快):
c = "this is a string"
创建一个新的String
,并分配给c
。
d = c
将d
绑定到绑定的任何c
,即第1行的String
。
c.upcase!
将消息upcast!
发送到通过取消引用String
获得的c
。 String#upcase!
被定义为使接收者变异。因此,String
和c
都引用的d
现在已更改。
c = "the string has been edited"
创建一个与另一个无关的全新String
,并将其分配给c
。
p d
d
从未被重新分配,因此,它仍然绑定到第1行的String
上。
答案 1 :(得分:2)
通常-红宝石变量保存引用,而不是指向值的指针。分配时:
a = [3]
b = a
b
引用与a
相同的数组。字符串也一样。
值得一读: https://robertheaton.com/2014/07/22/is-ruby-pass-by-reference-or-pass-by-value/
编辑:
a = [1]
b = a
b
# => [1]
a = [2]
a
# => [2]
b
# => [1]
答案 2 :(得分:1)
我做过任何红宝石编程已经很长时间了,但是我记得: 简而言之,int按值存储,复杂类型按指针存储
例如:
ProjectA
这将创建一个内存占位符,在其中存储类型为'int'的所有id,同时也存储值本身(3)。
而:
a=3
这将初始化占位符,其ID类型为“字符串”,并指向另一个保存“ Toto”的内存的指针。
这就是为什么:
a="Toto"
a将为6,b将为3(指令a = 6不变)
而:
a=3
b=a
a=6
a和b将是相同的字符串