由帕斯卡引用传递

问题描述 投票:1回答:2

我不知道如果我理解正确的是如何通过引用传递的帕斯卡工作。它创建一个别名如在C ++(https://isocpp.org/wiki/faq/references)或它与C同样地工作,并且该过程获得的指针变量和使用该指针。

我想我可以提出我的问题是:通过引用是否帕斯卡尔支持实际移动,或者它被调用来完成通过共享。

例如FreePascal的参考状态,即该过程得到一个指针(https://www.freepascal.org/docs-html/current/ref/refsu65.html),但根据https://swinbrain.ict.swin.edu.au/wiki/Pass_by_Value_vs._Pass_by_Reference#Conclusion并且例如https://cgi.csc.liv.ac.uk/~frans/OldLectures/2CS45/paramPassing/paramPassing.html#callByReference通过引用传递以帕斯卡原理不同比C(其中指针被传递)。

如果任何人都可以解释多一点的差异或如何传递的参照意义已经改变(在现代语言,我们说通过引用传递,但其实他们是按值传递,例如像Java的)。那么什么是按引用传递的原始意义,它是如何工作的?它是怎样然后帕斯卡尔?

非常感谢你。

parameter-passing pass-by-reference pascal
2个回答
2
投票

Pass by reference

在Delphi,通过引用传递(使用VAR或出)指传递指针。但是请注意,有语义之间的差异“按值传递”或与实际通过“按引用传递”。

VAR或出

与C不同的是不实际的传递(通过指针),正是这些关键字的意思。变种简单地通过引用传递。走出对待某些托管类型不同,因为出来,你告诉编译器的输入值不能保证被初始化。否则,这些在技术上是相同的(但不是语义):(IOW,指针)的初始值传递的地址。

语义<>实际传递

Semantics

  • 通通过值的语义是日常获取原始值的本地副本,并且该例程可以(如果允许的话),而不会影响原来的更改。这些变化适用于本地副本,并走在程序结束时。
  • 通通过引用的语义是您访问(也许modiyfing)原件。

Actual low level passing may be different

但实际产生的代码可能是不同的,优化的原因。特别是较大的结构(有多大取决于版本和平台 - 这是地方文件,并随时间发生变化)经常通过引用(如指针),即使语义说按值传递。在该例程中(即在第一begin之前运行的隐藏代码)的序幕这种结构被复制到程序的本地帧。请注意,这不是在所有的调用约定完成。有时,一个完整副本的参数堆栈在拨打电话前,没有指针传递。

因为你还有一个本地副本,并没有修改原来,这仍然被认为是按值传递,就像你声明。所有的技术的东西都是透明的用户,所以区别只是在一个较低的水平。这只事项如果你写汇编程序或在CPU窗口必须阅读生成的代码。

Const

如果一个值参数声明const,原来是不无论如何修改,因此也可以省略大型结构到本地帧的复制和值可以访问(只读)由参考(指针),即使语义按值传递。小值总是通过了由值(在寄存器或堆栈),在这种情况下。

虽然它没有任何意义有const var作为参数修饰符(东西要么是常量或变量,但不能同时),你仍然可以强制路过一个const参数参考,使用[ref]修改属性:const [ref] X: Integer[ref] const X: Integer。整数通常会被传递由值(在寄存器或堆栈上,这取决于调用约定和平台)。

引用类型

请注意,如果您按值传递引用类型(如对象,动态阵列等),传值语义只适用于引用自己,即你让他们的副本,你可以在不影响原有的修改提供参考。

但是:物品(对象,阵列等)上这些点的引用可以被修改。只有引用本身是本地副本,而不是它们所指向的内容。所以,如果你调用一个方法上按值传递的对象引用,该对象(在堆)可毕竟修改!那还不是因为通过按值或传递作为const的不正常工作,但因为什么引用。

结论

  • 通由值意味着原始的副本是由和该副本可以在本地进行修改。
  • 通过引用传递装置的参考(指针)到原来的被传递的任何修改修改原始。
  • 引擎盖下,在技术上,在由值语义通,指针可以被后全部通过。如果必要的话,原来的一份拷贝,所以原来不被修改后所有。
  • 由值或甚至为const通过引用类型并不意味着它们指向被修改防止了原始(堆)的项目。没有C ++ - 像常量的概念,以防止这一点。

多一点关于引用和指针可以在我的(非常流行)的文章Addressing pointers被发现。


1
投票

一个简单的答案比(非常好)等。

做它与C同样地工作,并且该过程获得的指针变量和使用该指针。

是的,这是引擎盖下会发生什么。该程序得到真正的指针,地址,给变量。但是编译器,明知,使其透明。所以,这里声明了一个参数“a”,该语句的过程中:

a := a div 2;

可以用两种不同的方式进行编译。如果a参数正常,即按值传递的声明,该声明被编译,如:

1 - 在地址“a”加载值 2 - 由两个整数除法 3 - 结果存储在地址“一”

相反,如果该参数被宣布为var,意思是通过引用传递时,编译器:

1 - 在地址“a”加载值 2 - 在刚刚加载地址加载值(这是一个指针引用) 3 - 分 4 - 回存

以上四个语句完全什么C编译如果来源是:

*a = *a / 2;

我想我可以提出我的问题是:通过引用是否帕斯卡尔支持实际移动...?

答案是绝对肯定的,真正的引用传递,并没有太多的语言做这么好,干净。用于调用过程的源代码不改变,过程是否被称为以“通过参考”或“由值”。再次编译,知道形式参数如何被传递,隐藏的细节,与C.例如,拿一个呼叫到其中希望通过值传递的参数的过程:

myproc(a);  // pascal and C are identical

如果程序期望通过引用传递事情变得不同:

myproc(a);  // pascal: identical to before

myproc(&a); // C: the language does not hide anything

关于最后一点,有人认为C是最好的,因为它迫使程序员知道,通过变量可以由程序(功能)进行修改。我认为,取而代之的是,Pascal是更优雅,而程序员无论如何都应该知道是什么程序就行了。

这一切是“简单”的类型。如果我们谈论的字符串(和现代帕斯卡有他们的两个版本),这是相同的 - 帕斯卡。编译器的副本,增加引用计数,确实无论是需要有通过值或引用传递的全力支持。 C语言中没有类似的东西。

如果我们谈论班,情况就不同了,但他们必须无论如何不同,因为类的语义。

我希望能有补上一其他完整的答案。

© www.soinside.com 2019 - 2024. All rights reserved.