【发布时间】:2020-06-08 09:16:26
【问题描述】:
运行此问题中提供的代码:
Why move return an rvalue reference parameter need to wrap it with std::move()?
#include <string>
#include <iostream>
#include <utility>
template<typename T>
class TD;
class Widget {
public:
explicit Widget(const std::string& name) : name(name) {
std::cout << "Widget created with name: " << name << ".\n";
}
Widget(const Widget& w) : name(w.name) {
std::cout << "Widget " << name << " just got copied.\n";
}
Widget(Widget&& w) : name(std::move(w.name)) {
std::cout << "Widget " << name << " just got moved.\n";
}
private:
std::string name;
};
Widget passThroughMove(Widget&& w) {
// TD<decltype(w)> wType;
// TD<decltype(std::move(w))> mwType;
return std::move(w);
}
Widget passThrough(Widget&& w) {
return w;
}
int main() {
Widget w1("w1");
Widget w2("w2");
Widget wt1 = passThroughMove(std::move(w1));
Widget wt2 = passThrough(std::move(w2));
return 0;
}
根据我使用的编译器产生不同的结果。使用最新的 Visual Studio 编译时(尝试了 C++14 和 C++17),我得到以下结果:
Widget created with name: w1.
Widget created with name: w2.
Widget w1 just got moved.
Widget w2 just got moved. //<---
在线运行并编译此代码,结果不同。在提供的问题中,用户也会收到相同的结果:
Widget created with name: w1.
Widget created with name: w2.
Widget w1 just got moved.
Widget w2 just got copied. //<---
为什么 w2 在使用 Visual Studio 时会被移动,而在使用各种不同的编译器时会被复制?
【问题讨论】:
-
一个问题应该是自包含的。可以删除链接的问题。
-
发生这种情况主要是因为 msvc(vs 默认使用的编译器)正在使用不同的实现,这些实现对于它的许多函数/类来说不是标准的。一个很好的例子是 std::exception,对于许多编译器来说,它是一个几乎不做任何事情的对象,但在 msvc 中,它可以将字符串作为其构造函数的参数,并且还有一个 .what() 函数允许打印它。我不确定这里是否也是这种情况,但很可能是。如果我错了,请纠正我,因为我也很好奇!
-
@GhostyFrosty 在这种特殊情况下,MSVC 从 MSVC v19.24 开始简单地击败了 Clang 和 GCC 来实现 P1825R0。
标签: c++ visual-c++ rvalue-reference