将pass-by-value作为参考返回时会发生什么?

Ble*_*eek 2 c# java pass-by-value

好吧,在你跳起来之前,你需要了解与pass-by-ref相比的传值.您可能不同意传值的这个定义,但这仅仅是语义,因为真正的问题是堆栈分配和堆分配之间发生的事情.

Pass-by-value:复制要传递的对象,并将对象的副本作为参数提交给函数(好的,OO纯粹主义者,你喜欢称之为"方法" - 语义!).因此,在函数的结束/返回时,不管对象的副本做了什么,都不会修改原始对象.

因此Java(也可能是C#)是一种按值传递的语言.有些人认为它们是pass-by-ref,但实际上传递的args是引用.因此,引用的副本将传递给函数.也就是说,引用是按值传递arg,因为原始引用在函数的结束/返回时不会更改.

现在我们已经把这个拿走了,接受了我的价值传递,这就是问题所在.

因此,函数参数是原始对象/引用的副本.它在堆栈上分配.堆栈很好,因为在函数的结束/返回时简单地立即丢弃分配的值.当我的函数从堆栈中获取pass-by-value arg并返回它时会发生什么.看,它在堆栈上.是否将该对象/引用的堆栈alloc复制并重新分配到堆上?

Java和C#究竟/精确地发生了什么?

Ray*_*oal 7

听起来你在问Java中这样的东西有什么影响:

public static void f(Object object) {
    return object;
}

public static void g() {
    Dog dog = new Dog("Spike");
    System.println(f(dog));
}
Run Code Online (Sandbox Code Playgroud)

如果是这样,答案是,当调用g时:

  1. 内存在堆上分配,并且g中称为dog的堆栈分配变量用于引用此内存.狗的"价值"是对象的参考; 它占用了一个记忆词.

  2. 该值的副本通过寄存器或堆栈传递给f.f获取自己的堆栈帧,除非编译器优化掉.但是,让我们说它确实得到了一个堆栈框架.包含地址副本值的简单单词放在此堆栈帧中.实际上,它与以某种方式传递普通旧整数没有什么不同,正如您正确地指出Java中的所有内容都是按值传递.

  3. 当f返回时,它传递object的值,它本身只是一个指向原始Dog对象的内存字,返回给它的调用者.这个简单的指针值通常通过寄存器传回.关键是,只传回一个单词.