【发布时间】:2021-09-09 07:32:31
【问题描述】:
我正在研究 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;
}
(附带说明,如果我实际上不使用 std::move,尽管编译时没有优化,但 lldb 甚至不会让我在移动构造函数中设置断点。)
很高兴收到任何和所有澄清!
【问题讨论】:
-
它不动是因为“没有工作比一些工作少”(从 CPPCon 谈话中无耻地窃取的引述):en.cppreference.com/w/cpp/language/copy_elision
-
在非常不正式的措辞中,任何有名字的东西都是左值。
r是一个有名字的变量。这是一个左值。 NRVO 涵盖了此用例,这是一种编译器优化,很可能会删除副本(如果您不使用std::move)。 -
@RichieHH 是的。并且从 c++17 开始,您具有强制复制省略 (RVO),可以保证即使移动也可以省略。
-
@RichieHH 在 c++17 之前是编译器优化,在 c++17 之后是有保证的。例如,如果您同时删除了复制和移动构造函数,代码将无法编译,即使优化后的代码实际上并未使用它。
-
@Debashish:
std::vector的一些方法需要noexcept在内部使用移动而不是复制。
标签: c++ c++11 move-constructor