在Effective Modern C ++的第25项(170p~171p)中,代码如下所示:
class Widget {
public:
void setName(const std::string& newName) // set from
{ name = newName; } // const lvalue
void setName(std::string&& newName) // set from
{ name = std::move(newName); } // rvalue
…
};
w.setName("Adela Novak");
使用setName的版本作为通用引用,字符串 文字" Adela Novak"将传递给setName,它将在那里 传递给w内的std :: string的赋值运算符。 W公司 因此,名称数据成员将直接从字符串中分配 文字; 不会出现临时的std :: string对象。
我不明白为什么" 不会出现临时的std :: string对象"如果调用setName的版本采用通用引用。不应该将 newName 创建为临时std :: string吗?
答案 0 :(得分:4)
代码前面是
template<typename T> void setName(T&& newName) // newName is { name = std::forward<T>(newName); } // universal reference
稍后会出现您复制到问题中的代码。然后,在你引用的文字之前:
在这种情况下肯定会有效,但也有缺点。 [...]例如,考虑使用
setName
:w.setName("Adela Novak");
之后立即:
使用
setName
的重载版本,[...]
该文中说,除了你引用的代码之外,其他代码中不会出现临时字符串对象。你严重误读,结果错误地引用了文本。
答案 1 :(得分:2)
第25项的名称如下:在左值引用上使用std::move
,在通用引用上使用std::forward
。
您提供的代码不包含带有通用引用的setName
版本。就像这样:
template <class T>
void setName(T&& t) {
name = std::forward<T>(t);
}
此版本将避免创建临时。