函数返回结构体,则编译器会为返回值做一次寄存器的来回拷贝,是多余动作吗?解决思路

函数返回结构体,则编译器会为返回值做一次寄存器的来回拷贝,是多余动作吗?
x86结构下的C++编译器例如VC,如果返回的是基本类型,那么就caller结束直接放到eax里面,caller从eax里面拿到返回值,放入一个堆栈变量。
但是我发现,如果返回的是一个结构体(哪怕是只有一个int的结构体)返回的行为会不一样。例如:
C/C++ code

int foo(){
    int ret=44;
    return ret;
};
int main( void){
    int iret=foo(); 
    return 0;
}


那么foo在返回前就把ret放到eax里面: mov eax, DWORD PTR _ret$[ebp]
在main函数里面call了foo之后: mov DWORD PTR _iret$[ebp], eax,把eax的值放入iret局部变量。

这理解起来都没有问题。但是我稍微改了一下代码:
C/C++ code

struct s{
    int a;
};
s foo(){
    s s1={44};
    return s1;
};
int main( void){
    s s2=foo(); 
    return 0;
}

foo函数在返回值钱也是把s1中的一个值放入eax: mov eax, DWORD PTR _s1$[ebp]
但是main函数的行为发生了变化,在call函数foo之后,代码变成了:

  00036 e8 00 00 00 00 call ?foo@@YA?AUs@@XZ ; foo
  0003b 89 45 f8 mov DWORD PTR $T2556[ebp], eax ; 从eax到内存
  0003e 8b 45 f8 mov eax, DWORD PTR $T2556[ebp] ; 再从内存在eax
  00041 89 45 fc mov DWORD PTR _s2$[ebp], eax

我不知道先把eax的值mov到DWORD PTR $T2556[ebp],在下面一句话mov回eax,这样做有什么意义?
直接第三句话mov DWORD PTR _s2$[ebp], eax不就解决问题了么?

------解决方案--------------------
这是没有优化的代码 完全按照源码指定的行为进行操作 你把优化打开肯定大不一样
------解决方案--------------------
第一,编译器的优化程度视编译器而定,不由C++标准强制规定

第二,C++中的结构体本质上是默认public权限的类,而类有构造析构复制函数等,优化时肯定要考虑这些,不能像基础数据类型一样直接复制——哪怕是一个只有int成员的结构体,起码也有自己的this指针这个隐藏变量。