首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >与其他语言相比,Ruby和指针?

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

Stack Overflow用户
提问于 2019-08-30 13:43:58
回答 3查看 913关注 0票数 3

我对ruby相当陌生,但来自C/C++背景,我相信我对计算机和编程的工作原理有基本的了解。

在C++中,如果您想要创建指向某个值的指针,您将将其指定为指针:http://www.cplusplus.com/doc/tutorial/pointers/

示例:

代码语言:javascript
运行
复制
int x = 3;
int *p = &x;
*p = 4;
std::cout << x;

这对我来说很有意义,因为现在p指向x的地址,因此当我们改变p的值时,x也会改变。在本例中,x将输出4。

但当我跑的时候

代码语言:javascript
运行
复制
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?为什么整数不指向另一个变量的地址?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-08-30 13:48:39

通常- ruby变量保存引用,而不是指向值的指针。当你分配:

代码语言:javascript
运行
复制
a = [3]
b = a

b引用与a相同的数组。字符串也是一样的。

值得一读:https://robertheaton.com/2014/07/22/is-ruby-pass-by-reference-or-pass-by-value/

编辑:

代码语言:javascript
运行
复制
a = [1]
b = a
b
# => [1]
a = [2]
a
# => [2]
b
# => [1]
票数 2
EN

Stack Overflow用户

发布于 2019-08-30 15:29:19

为什么在ruby中数组被看作是指针,它是如何工作的?

在Ruby中没有“指针”这样的东西。

b是否像在C++中那样指向a的地址?

在Ruby中没有像“地址”这样的东西。语言规范指出,当您取消引用一个变量时,它的计算结果是分配给该变量的最后一个对象。语言实现是如何做到这一点的,这是完全不相关的,您不应该,实际上也不可能知道。它可以使用指向内存位置的指针。可能需要一本字典。它可以把价值打印在纸上,然后传真到东亚的一家血汗工厂,儿童奴隶在那里解释它。(这将是极不道德、不道德和非法的,但这将是一个完全有效的实施。)

是什么使变量改变了它所指向的?

赋值,而且只有赋值才能更改变量的绑定。

例如:如果a = b,什么时候a != b

!=方法被重写以便这么说的时候。这可能是个糟糕的主意,但尽管如此:

代码语言:javascript
运行
复制
class Foo
  def !=(*)
    false
  end
end

a = Foo.new
b = a

a != b #=> false

为什么整数不指向另一个变量的地址?

再说一遍,Ruby中没有“指针”或“地址”这样的东西,因此,整数永远不能“指向”“地址”,因为“指向”和“地址”是Ruby中不存在的概念。

让我们逐行遍历您的代码:

代码语言:javascript
运行
复制
a = []

创建一个新的Array对象,并将局部变量a绑定到该新数组对象。

代码语言:javascript
运行
复制
b = a

现在,将局部变量b绑定到计算表达式a的结果。计算仅由变量名称组成的表达式的结果是什么?变量被取消引用,也就是说,它的计算结果是先前绑定到该变量的对象。

在本例中,该对象是您在第1行中创建的Array

代码语言:javascript
运行
复制
a[0] = 3

这一行只是下面一行的语法糖:

代码语言:javascript
运行
复制
a.[]=(0, 3)

在这里,您将发送消息[]=,将两个参数03传递给取消引用局部变量a的结果。再一次,取消引用局部变量a的计算结果是该变量绑定到最后的任何变量,即第1行中的Array。方法Array#[]=被定义为对其接收器进行变异,以便将第二个参数放置在第一个参数指定的索引上。

这种方法不需要改变它的接收器。它还可以返回Array的更新副本。(虽然在这种特殊情况下,这是无用的,因为a[0] = 3语法糖的行为就像赋值一样,因此总是计算到右边。换句话说,除非使用调用语法Array#[]=的显式方法,否则将忽略a.[]=(0, 3)的返回值。)

代码语言:javascript
运行
复制
p b

在这里,我们再次取消对局部变量b的引用,它仍然指向完全相同的对象(从来没有任何重新分配),它仍然是第1行中的Array

在整个代码中只有一个Array。您从未创建过第二个Array,也从未调用将返回一个新的的方法。

一个确实返回新的Array而不是变异接收器的方法是Array#+方法。下面是一个使用Array#+的备用示例

代码语言:javascript
运行
复制
a = []
b = a
a += [3]

a += [3]等价于a = a + [3],而后者等价于a = a.+([3])。因此,我们取消引用a,它从第1行给出Array,然后用单个参数[3]向它发送消息+Array#+被定义为返回一个新的Array,它是接收方和参数的级联。最后,我们将这个新的Array分配给局部变量a

代码语言:javascript
运行
复制
p b

局部变量b仍然绑定到同一个对象,因为我们从未重新分配它。因此,它仍然绑定到第1行的Array上。我们从未更改过这个Array,因此,它会打印[]

关于您的第二个例子(这次我会更快一点):

代码语言:javascript
运行
复制
c = "this is a string"

创建一个新的String,分配给c

代码语言:javascript
运行
复制
d = c

d绑定到绑定到的任何c,即第1行中的String

代码语言:javascript
运行
复制
c.upcase!

将消息upcast!发送到取消引用c获得的StringString#upcase!被定义为对接收器进行变异。因此,被cd引用的c现在已经改变了自己。

代码语言:javascript
运行
复制
c = "the string has been edited"

创建一个与另一个无关的全新String,并将其分配给c

代码语言:javascript
运行
复制
p d

d从未被重新分配,因此,它仍然绑定到第1行的String上。

票数 4
EN

Stack Overflow用户

发布于 2019-08-30 14:14:28

我已经很久没有做过任何ruby编程了,但我记得:简而言之,int是按值存储的,复杂类型是通过指针存储的。

例如:

代码语言:javascript
运行
复制
a=3

这将创建一个内存位置保持器,其中存储类型'int‘的任何id,并且存储值本身(3)。

同时:

代码语言:javascript
运行
复制
a="Toto"

这将使用类型为"string“的id和指向另一个持有"Toto”的内存的指针初始化位置持有人。

这就是为什么:

代码语言:javascript
运行
复制
a=3
b=a
a=6

A为6,b为3(未被指令a=6更改)

同时:

代码语言:javascript
运行
复制
a="Toto"
b=a
a.upcase!

A和b将是相同的字符串。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57727934

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档