调用非 void 函数而不使用其返回值。实际发生了什么?

2022-09-03 05:17:36

所以,我在这里发现了一个类似的问题,但答案更多的是关于风格以及你是否能够做到这一点。

我的问题是,当你调用一个返回对象的非void函数,但你从未分配或使用所述返回的对象时,实际上会发生什么?所以,关于你是否能做到,因为我绝对知道你可以理解上面链接的另一个问题......编译器/运行时环境有什么作用?

这不是一个特定于语言的问题,但如果你回答,请指定你所指的语言,因为行为会有所不同。


答案 1

我相信对于C#和Java,结果最终都会出现在堆栈上,然后编译器会强制弹出指令忽略它。埃里克·利珀特(Eric Lippert)关于“虚空是不变的”的博客文章对此有更多信息。

例如,请考虑以下 C# 代码:

using System;

public class Test 
{
    static int Foo() { return 10; }
    
    public static void Main()
    {
        Foo();
        Foo();
    }
}

为该方法生成的 IL(由 MS C# 4 编译器)为:Main

.method public hidebysig static void Main() cil managed
{
    .entrypoint
    .maxstack 8
    L_0000: call int32 Test::Foo()
    L_0005: pop 
    L_0006: call int32 Test::Foo()
    L_000b: pop 
    L_000c: ret 
}

请注意对 - 的调用,如果创建 void 方法,这些调用将消失。popFoo


答案 2

编译器是做什么的?

编译器生成一个 pop 指令,该指令从虚拟堆栈中丢弃结果。

运行时环境有什么作用?

它通常将代码转换为代码,该代码将返回值传递回寄存器中,而不是堆栈位置。(通常在 x86 体系结构上采用 EAX。

抖动知道该值将未被使用,因此它可能会生成清除寄存器的代码。或者它可能只是让它在登记册中徘徊了一段时间。

您关心哪个运行时环境?有很多,他们都有不同的紧张情绪。