C++ 返回值的两个副本

C++ 返回值的两个副本,c++,gcc,C++,Gcc,我正在按函数分析返回值。实际问题见下文: struct S{ int a, b, c, d; }; S f(){ S s; s.b=5; return s; } int main(){ S s= f(); s.a =2; } 编译器输出来自: 我有什么问题 为什么有两个拷贝构造函数?我不明白为什么它是必要的 调用构造函数以生成用作f()返回值的临时对象的两次之一。如果要避免这种额外的开销,您必须依赖于调用构造函数的两次操作之一,以构建用作f()返回值的临时对象。如果您想避免

我正在按函数分析返回值。实际问题见下文:

struct S{ int a, b, c, d;  };
S f(){
 S s;
 s.b=5;
 return s;
}

int main(){
  S s= f(); 
  s.a =2;
}
编译器输出来自:

我有什么问题

  • 为什么有两个拷贝构造函数?我不明白为什么它是必要的

  • 调用构造函数以生成用作
    f()
    返回值的临时对象的两次之一。如果要避免这种额外的开销,您必须依赖于调用构造函数的两次操作之一,以构建用作
    f()
    返回值的临时对象。如果您想避免这种额外的开销,就必须依赖于。

    调用
    f()
    中的copy构造函数,因为使用了对象的“return”。这将提示它创建一个临时变量的副本,然后将其传递到
    main
    。main中的Copy构造函数很明显
    f()
    返回一个
    S
    对象,它被复制到“
    S

    调用
    f()
    中的Copy构造函数,因为使用了带对象的“return”。这将提示它创建一个临时变量的副本,然后将其传递到
    main
    。main中的Copy构造函数是显而易见的
    f()
    返回一个
    S
    对象,它被复制到“
    S

    非ono,代码比链接好。顺便说一句,这个链接看起来很疯狂,并且被格式化为代码,所以如果你不想在这里发布完整的代码,可能没有人会访问它。但至少发布一个有问题的最低版本describe@ForceBru-锁销连杆有什么问题@Chris如果你看一下,你会发现所有这些注释都是在Simple从linkshortener导入代码之前出现的。大多数评论只是/主要集中在这里没有代码。@重复数据消除:这里从来没有一个链接缩短器,只有一个完整的~1k字符的godbolt.org链接,它将完整的源代码和编译器选项编码到URL中。但是,是的,您应该始终发布至少一段代码和您正在谈论的asm,并提供一个godbolt链接,以便人们可以使用不同的编译选项或对源代码的修改轻松地进行尝试。很明显,这个链接应该作为一个链接发布,带有一个对不知道的人可能有意义的描述。在编辑之前这是一个可怕的问题。不,代码比链接好。顺便说一句,这个链接看起来很疯狂,并且被格式化为代码,所以如果你不想在这里发布完整的代码,可能没有人会访问它。但至少发布一个有问题的最低版本describe@ForceBru-锁销连杆有什么问题@Chris如果你看一下,你会发现所有这些注释都是在Simple从linkshortener导入代码之前出现的。大多数评论只是/主要集中在这里没有代码。@重复数据消除:这里从来没有一个链接缩短器,只有一个完整的~1k字符的godbolt.org链接,它将完整的源代码和编译器选项编码到URL中。但是,是的,您应该始终发布至少一段代码和您正在谈论的asm,并提供一个godbolt链接,以便人们可以使用不同的编译选项或对源代码的修改轻松地进行尝试。很明显,这个链接应该作为一个链接发布,带有一个对不知道的人可能有意义的描述。同意在编辑之前这是一个可怕的问题。何时生成临时对象(请给我行数)@Gilgamesz:在这种情况下,您应该使用任何级别的优化进行编译(即使是最小的
    -Og
    优化以进行调试,以及
    f()
    将编译为
    movabq$21474836480,%rax
    /
    movl$0,%edx
    /
    ret
    main()
    当然会完全优化。)当构建临时对象时(请给我行数)@Gilgamesz:在这种情况下,您应该只需进行任何级别的优化即可(即使是最小的
    -Og
    也会为调试而优化,而
    f()
    也会编译成
    movabsq$21474836480,%rax
    //
    ret
    main()
    当然会完全优化。)
    f():
            pushq   %rbp
            movq    %rsp, %rbp
            subq    $32, %rsp
            movl    $5, -28(%rbp)
            leaq    -32(%rbp), %rdx
            leaq    -16(%rbp), %rax
            movq    %rdx, %rsi
            movq    %rax, %rdi
            call    S::S(S const&)
            movq    -16(%rbp), %rax
            movq    -8(%rbp), %rdx
            leave
            ret
    main:
            pushq   %rbp
            movq    %rsp, %rbp
            subq    $32, %rsp
            call    f()
            movq    %rax, -16(%rbp)
            movq    %rdx, -8(%rbp)
            leaq    -16(%rbp), %rdx
            leaq    -32(%rbp), %rax
            movq    %rdx, %rsi
            movq    %rax, %rdi
            call    S::S(S const&)
            movl    $2, -32(%rbp)
            movl    $0, %eax
            leave
            ret