为什么通用引用和右值引用的流程不同
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 &&
可能同时绑定到右值和左值。
从 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 &&
可能同时绑定到右值和左值。