为什么通用引用和右值引用的流程不同

Why the difference in the flow of universal reference and rvalue reference

从 Efficient Modern C++ 开始,第 25 项。我们有一个例子

案例一

class Widget {
public:
template<typename T>
void setName(T&& newName)
{ name = std::forward<T>(newName); }
...
};

案例二

class Widget {
public:
void setName(const std::string& newName)
{ name = newName; }
void setName(std::string&& newName)
{ name = std::move(newName); }
...
};

来电

Widget w;
w.setName("Adela Novak");

现在假设情况 1,书中指出文字被传送给 w 的名称数据成员内的 t std::string 的赋值运算符。

假设情况 2,书中指出 -> 首先从文字创建一个临时文件,调用字符串构造函数,因此 setName 参数可以绑定到它,然后将这个临时文件移到 w 的名称数据成员中。

问题

为什么会出现这种行为差异,我该如何考虑?

也就是说,为什么情况 1 不需要临时的?为什么会有差异? T&& 是否未被推导为对字符串的右值引用,从而达到与案例 2 相同的行为(显然不是,根据本书,但为什么)?

在情况 1 中,T 被推断为 const char (&)[12],而不是 std::string。编译器还没有理由将字符串文字提升为 std::string。在情况 2 中,每个重载都需要引用 std::string,这会强制创建一个临时 std::string,可以使用隐式 const char* 构造函数将引用绑定到该临时 std::string

请注意,虽然 std::string && 等右值引用可能仅绑定到右值,但模板化的等价物 T && 可能同时绑定到右值和左值。