读取rust tutorial托管和拥有的指针可以传递给需要借用指针的函数,并在编译时转换为借用指针。
为什么不能以相同的方式传递堆栈变量?什么语法或特性要求显式&
运算符传递那个,而不是编译器自动转换它?
struct Point {x: float, y: float}
let on_the_stack : Point = Point {x: 3.0, y: 4.0};
let managed_box : @Point = @Point {x: 5.0, y: 1.0};
let owned_box : ~Point = ~Point {x: 7.0, y: 9.0};
fn compute_distance(p1: &Point, p2: &Point) -> float {
let x_d = p1.x - p2.x;
let y_d = p1.y - p2.y;
sqrt(x_d * x_d + y_d * y_d)
}
compute_distance(&on_the_stack, managed_box);
compute_distance(managed_box, owned_box);
引起混淆的是kibwen对ycombinator的引用(我找不到原始报价,但这里是报价的引用)
我们仍然会有&和& mut,但那些不是指针,它们是引用(在我们的文档中称它们为“借用指针”是我们自己的错误)
如果compute_distance
正在引用并且编译器自动将指针转换为引用,为什么它不能对值执行相同操作?
编辑:由于pnkfelix似乎知道他在说什么,我会在这里复制一些对话以便于阅读。
pnkfelix
Rust的设计者决定在这方面不遵循C ++的路径。这个决定的一个副作用是,当读取代码的人看到Rust中的f(x,y)之类的调用时,人们不必花时间想知道“等待,f如何获取其参数;如果它改变y,将会我看到反映在f之后回来了吗?x怎么样?“等
J V
我可能会对引用的性质感到困惑。生锈中的
@var
和~var
是指针(虽然它们的行为更像引用) - C ++引用只是指针下的指针吗?在任何情况下,我都可以在C代码可读性方面应用相同的逻辑。
变量可以是值或指针(你只需要像生锈一样传递变量:
f(var)
)或者在函数调用中引用(就像你在rust中所做的那样:f(&var)
) - I本来以为生锈编译器会识别函数签名并自动处理。我没有看到对C或C ++的改进
pnkfelix
一个跟进:我写的这一行:“等等,f如何接受它的论点;如果它改变了y,我会看到f在f返回后反映出来吗?x怎么样?”有点滑稽,因为即使像f(& x,y)这样的调用也无法修改x;它必须是f(& mut x,y)。 (并且x本身的声明必须让mut x = ...等 - pnkfelix 1小时前
第二次跟进:为什么显式& x在Rust中比在C / C ++中更重要(而不是让f(x,y)隐含地执行借用& x),这是因为借用检查器强制借用遵循某些规则,并拒绝编译不符合的代码。当你从借用检查器得到一个错误时,如果编译器在源代码中指向形式为& x或& mut x的表达式,那么它是一个更好的用户体验,而不是指向函数调用并说“这里有隐含的借款。” (那当然是主观意见。) - pnkfelix 1小时前
我看到你在回复中有一个后续注释,但我不明白你在将“相同的逻辑应用于C”时所做的一点。如果你的意思是C而不是C ++,那么你通常必须在调用需要指针的函数时显式地获取内存地址。如果函数需要
int**
,那么有人需要执行&E
,其中E
是类型为int*
的l值。这似乎与Rust类似。 (我从C中回想起的主要例外是函数指针;你不需要&f
来创建指向f
的函数指针。) - pnkfelix 1小时前
J V
这似乎与Rust类似。 - 完全是我的观点 - 从可读性的角度来看,与普通C. 相比没有太大的改进,因为借用检查员的力量借用了某些规则...而是指向一个函数调用并说“这里有一个隐含的借用。” Bingo - 这是我寻找的潜在原因之一。如果您发现手动演员的任何其他原因,请随时添加到您的答案中!
答案 0 :(得分:3)
我认为目的是让读者清楚地了解结构的副本,而不是传递对现有结构的引用。 (更多内容见下文。)
列出的示例中的托管框和拥有框已经是引用;它们只是暂时从一种引用(分别为@Point
和~Point
)转换为&Point
引用。但它们都只是引用,并且没有复制引用的存储。
很可能Rust编译器可以根据被调用函数的类型签名推断何时需要创建引用而不需要复制struct时
确实,这正是C ++编译器在看到f(x, y)
之类的调用时所做的事情:它需要查看f
的签名,例如f(A &a, B b)
,并从中确定:“好的,我将为x参数创建一个引用(假设它是A类型)并创建y参数的副本(假设它是B类型),因为它是按值传递的。”< / p>
Rust的设计者决定在这方面不遵循C ++的路径。这个决定的一个副作用是,当读取代码的人看到Rust中的f(x, y)
之类的调用时,人们不必花时间思考“等待,f
如何接受其参数;如果它发生变异y
,我会在f
返回后看到这反映出来吗?x
怎么办?等
x
和y
的内存可到达 ...但我离题了。 )