什么时候需要显式调用 std::move 以及什么时候不在 cpp 中?

Hör*_*nHH 7 c++ move-constructor c++11

我正在阅读 Stroustrup 的“C++ v2 之旅”。这当然不是一本 C++ 初学者的书,但很有趣。

我用谷歌搜索了一下,但对这个没有任何兴趣。

现在,我想我明白编译器何时可以使用移动构造函数,但显然我不明白。在这里,我展示了移动构造函数以及我认为会使用它的函数。事实并非如此。仅当我明确使用 std::move 时。为什么是这样?我的理解是,本地r将在返回时隐式“移动”。

template<typename T>
Vector<T>::Vector(Vector<T> && a) // move constructor
     :elem{a.elem},sz{a.sz}{
     a.elem=nullptr;
     a.sz=0;
}

template<typename T>
Vector<T> moveVectorAfterAdd(const Vector<T> &  v1, const Vector<T> & v2){
     Vector<T> r =   v1+v2;
     return std::move(r);
     //return r;
}

int main(void) {
     Vector<double> v1(1);
     Vector<double> v2=v1;
     Vector<double> v3=v2;

     Vector<double> v4=moveVectorAfterAdd(v1,v2);

     return 0;
}
Run Code Online (Sandbox Code Playgroud)

(顺便说一句,如果我实际上不使用 std::move,尽管编译时没有进行任何优化,lldb 甚至不会让我在移动构造函数中设置断点。)

很高兴收到所有澄清!

eer*_*ika 7

什么时候需要显式调用 std::move 以及什么时候不在 cpp 中?

简而言之,技术上精确的话:当您有一个左值并且希望将其作为右值时,请使用 std::move。更实际的是:当您想要有一个副本而不是移动时,您会想要这样做。因此得名 std::move。

在示例中,您返回一个自动变量。使用 std::move 无法避免复制,因为在返回自动变量的特殊情况下,甚至从左值也会发生移动。

在这里,我展示了移动构造函数以及我认为会使用它的函数。事实并非如此。

仅仅因为抽象机中有一个移动,并不一定意味着会调用移动构造函数。这是一件好事,因为什么都不做可能比调用移动构造函数更快。

这称为(命名)返回值优化。或者更一般地说,复制省略。使用 std::move 会抑制这种优化,因此在这种情况下不仅没有必要,而且还会适得其反。