Ruby和指针与其他语言相比?

时间:2019-08-30 13:43:58

标签: c++ arrays ruby

我对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?为什么整数不指向另一个变量的地址?

3 个答案:

答案 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)

在这里,您正在发送消息[]=,该消息将两个参数03传递给取消引用局部变量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获得的cString#upcase!被定义为使接收者变异。因此,Stringc都引用的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将是相同的字符串