我对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在ruby中,b输出[3],而对于我来说,它不应该输出任何内容。d输出的是"THIS IS A STRING",而不是"the string has been edited"。Ruby and pointers是另一个问题,它们是如何在ruby中使用指针的。
,我的问题是:,为什么在ruby中数组被看作是指针,它是如何工作的?b是否像在C++中那样指向a的地址?是什么使变量改变了它所指向的地址?例如:如果a = b何时将a != b?为什么整数不指向另一个变量的地址?
发布于 2019-08-30 13:48:39
通常- ruby变量保存引用,而不是指向值的指针。当你分配:
a = [3]
b = ab引用与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]发布于 2019-08-30 15:29:19
为什么在ruby中数组被看作是指针,它是如何工作的?
在Ruby中没有“指针”这样的东西。
b是否像在C++中那样指向a的地址?
在Ruby中没有像“地址”这样的东西。语言规范指出,当您取消引用一个变量时,它的计算结果是分配给该变量的最后一个对象。语言实现是如何做到这一点的,这是完全不相关的,您不应该,实际上也不可能知道。它可以使用指向内存位置的指针。可能需要一本字典。它可以把价值打印在纸上,然后传真到东亚的一家血汗工厂,儿童奴隶在那里解释它。(这将是极不道德、不道德和非法的,但这将是一个完全有效的实施。)
是什么使变量改变了它所指向的?
赋值,而且只有赋值才能更改变量的绑定。
例如:如果
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!发送到取消引用c获得的String。String#upcase!被定义为对接收器进行变异。因此,被c和d引用的c现在已经改变了自己。
c = "the string has been edited"创建一个与另一个无关的全新String,并将其分配给c。
p dd从未被重新分配,因此,它仍然绑定到第1行的String上。
发布于 2019-08-30 14:14:28
我已经很久没有做过任何ruby编程了,但我记得:简而言之,int是按值存储的,复杂类型是通过指针存储的。
例如:
a=3这将创建一个内存位置保持器,其中存储类型'int‘的任何id,并且存储值本身(3)。
同时:
a="Toto"这将使用类型为"string“的id和指向另一个持有"Toto”的内存的指针初始化位置持有人。
这就是为什么:
a=3
b=a
a=6A为6,b为3(未被指令a=6更改)
同时:
a="Toto"
b=a
a.upcase!A和b将是相同的字符串。
https://stackoverflow.com/questions/57727934
复制相似问题