【问题标题】:Is returning an empty class in C++ is the same as returning nothing (void)?在 C++ 中返回一个空类与不返回任何内容(void)是一样的吗?
【发布时间】:2022-10-07 16:29:23
【问题描述】:

我想知道如果我返回一个空的、无成员的类/结构与什么都不返回(如在void-declared 函数中),在性能方面是否相同。

struct nothing {};

void func1()
{
};

nothing func2()
{
     return nothing{};
};

int main()
{
    func1();
    nothing n = func2();
}

这些对 func1 和 func2 的调用实际上会在现代编译器上产生相同的汇编输出吗?

    标签: c++ assembly optimization


    【解决方案1】:

    因此,我正在使用如下命令在 clang 14.0.6 上对此进行调查:

    clang++ -O0 -S -masm=intel test.cpp
    

    func1 结果:

        .globl  "?func1@@YAXXZ"                 # -- Begin function ?func1@@YAXXZ
        .p2align    4, 0x90
    "?func1@@YAXXZ":                        # @"?func1@@YAXXZ"
    # %bb.0:
        ret
                                            # -- End function
    

    虽然func2 导致:

        .globl  "?func2@@YA?AUnothing@@XZ"      # -- Begin function ?func2@@YA?AUnothing@@XZ
        .p2align    4, 0x90
    "?func2@@YA?AUnothing@@XZ":             # @"?func2@@YA?AUnothing@@XZ"
    .seh_proc "?func2@@YA?AUnothing@@XZ"
    # %bb.0:
        push    rax
        .seh_stackalloc 8
        .seh_endprologue
        mov al, byte ptr [rsp]
        pop rcx
        ret
        .seh_endproc
                                            # -- End function
    

    主要看起来是这样的(见注释行):

    main:                                   # @main
    .seh_proc main
    # %bb.0:
        sub rsp, 40
        .seh_stackalloc 40
        .seh_endprologue
        call    "?func1@@YAXXZ"
        call    "?func2@@YA?AUnothing@@XZ"
        mov byte ptr [rsp + 32], al         # -- This line is also a cost of 'nothing'
        xor eax, eax
        add rsp, 40
        ret
        .seh_endproc
                                            # -- End function
    

    我们实际上可以在这里看到一些预期的差异,因为空结构/类在 C++ 中实际上是 1 字节的长度,也可能需要额外的调试时指令来执行。

    然而,重要的是看看这是否会得到适当的优化,所以继续:

    clang++ -O1 -S -masm=intel test.cpp
    

    这次功能看起来相同:

        .globl  "?func1@@YAXXZ"                 # -- Begin function ?func1@@YAXXZ
        .p2align    4, 0x90
    "?func1@@YAXXZ":                        # @"?func1@@YAXXZ"
    # %bb.0:
        ret
                                            # -- End function
    
        .globl  "?func2@@YA?AUnothing@@XZ"      # -- Begin function ?func2@@YA?AUnothing@@XZ
        .p2align    4, 0x90
    "?func2@@YA?AUnothing@@XZ":             # @"?func2@@YA?AUnothing@@XZ"
    # %bb.0:
        ret
                                            # -- End function
    

    由于调用没有有意义的副作用,main 显然被清除了:

    main:                                   # @main
    # %bb.0:
        xor eax, eax
        ret
                                            # -- End function
    

    我们显然可以添加一些更复杂的逻辑,但是这次,我对在我当前有问题的范围内的结果感到满意,即,对于一个简单的内联可见范围,不返回任何内容与“返回”void 相同。

    【讨论】:

    • -O0 确实没有回答问题中的“在性能方面”。
    猜你喜欢
    • 2021-12-22
    • 1970-01-01
    • 2018-01-02
    • 1970-01-01
    • 1970-01-01
    • 2014-01-25
    • 2013-08-18
    • 2017-08-23
    • 1970-01-01
    相关资源
    最近更新 更多