低效 std::move()?

fet*_*tag 2 c++ move-semantics

请看下面的代码片段,在这种情况下 std::move() 的效率似乎很低。

class A {};

struct B {
    double pi{ 3.14 };
    int    i{ 100 };
    A* pa{ nullptr };
};

int main() {
    B b;
    std::vector<B> vec;
    vec.emplace_back(b);                // 1) without move
    vec.emplace_back(std::move(b));     // 2) with move
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我在 Visual Studio 2019 [C++ 14,发布] 中得到以下反汇编:

    vec.emplace_back(b);                // 1) without move
00E511D1  push        eax  
00E511D2  push        0  
00E511D4  lea         ecx,[vec]  
00E511D7  call        std::vector<B,std::allocator<B> >::_Emplace_reallocate<B> (0E512C0h)  
    vec.emplace_back(std::move(b));     // 2) with move
00E511DC  mov         eax,dword ptr [ebp-18h]  
00E511DF  cmp         eax,dword ptr [ebp-14h]  
00E511E2  je          main+91h (0E511F1h)  
00E511E4  movups      xmm0,xmmword ptr [b]  
00E511E8  movups      xmmword ptr [eax],xmm0  
00E511EB  add         dword ptr [ebp-18h],10h  
00E511EF  jmp         main+9Eh (0E511FEh)  
00E511F1  lea         ecx,[b]  
00E511F4  push        ecx  
00E511F5  push        eax  
00E511F6  lea         ecx,[vec]  
00E511F9  call        std::vector<B,std::allocator<B> >::_Emplace_reallocate<B> (0E512C0h)  
Run Code Online (Sandbox Code Playgroud)

很容易看出,移动版本需要更多不必要的工作。根据此处的描述,编译器将为结构 B 生成一个简单的移动构造函数,并且该简单的移动构造函数将采用复制语义

那么我的问题是:

  1. std::move() 对于这种情况是完全多余的。
  2. 此外,如果 std::move() 的参数有一个简单的移动构造函数,则 std::move() 是多余的。
  3. 如果简单的移动构造函数执行与简单的复制构造函数相同的操作,为什么编译器会生成不同的反汇编代码?事实上,这是我最困惑的。

eer*_*ika 6

  1. std::move() 对于这种情况是完全多余的。

从技术上讲这不是一个问题,但是是的,这是正确的。

  1. 此外,如果 std::move() 的参数有一个简单的移动构造函数,则 std::move() 是多余的。

与上面相同。

  1. 如果简单的移动构造函数执行与简单的复制构造函数相同的操作,为什么编译器会生成不同的反汇编代码?

可能是因为您在一个函数中调用了该函数std::move,但在另一个函数中没有调用该函数。

然而,它不必产生不同的程序集,因为可观察到的行为是相同的。我的编译器生成相同的程序集。