在实践中何时调用移动构造函数?
我最近了解了移动构造函数,但很多在线资源都没有讨论复制省略。复制省略对我来说也很有意义,但它让我想知道何时会在没有超级人为示例的情况下调用移动构造函数。
从一个流行的 SO 帖子向我解释了移动语义/sf/answers/217698701/
string b(x + y);
string c(some_function_returning_a_string());
帖子说这两个都应该调用移动构造函数,因为它们接受临时变量。但是,这些实际上都没有调用移动构造函数(我已经测试过),相反,它们都只是执行复制省略,除非您通过显式编写std::move.
string b(std::move(x + y));
string c(std::move(some_function_returning_a_string()));
或some_function_returning_a_string返回std::move(someString)。但你为什么要这样做?复制省略甚至比移动语义更高效。那么在什么情况下会调用移动构造函数而不是复制省略呢?
在你指出我这里之前,我觉得什么时候移动构造函数被调用?答案给出了人为的例子,或者他们中的一些人只是做了复制省略。我有兴趣学习在实践中何时调用移动构造函数。
这是测试的链接https://godbolt.org/z/KfczbboTr
回答
在您的示例中,从对象移动是暂时的,但移动时并非总是如此。有时我们知道我们可以移动,因为移动的 from 对象将不再使用,即使它不是临时的。考虑这种类型:
struct foo {
foo() = default;
foo(foo&& f) noexcept {
std::cout << "moven";
}
};
当您创建foos 的向量并且向量重新分配时,它不会复制元素,但会移动它们。例如:
#include <iostream>
#include <vector>
int main() {
std::vector<foo> v;
v.resize(5);
v.resize(v.capacity()+1); // force the vector to reallocate
}
输出:
move
move
move
move
move
复制或移动不可能被省略,因为元素在旧位置并且必须以某种方式到达内存中的新位置。