为什么"不会出现临时的std :: string对象"在Effective Modern C ++的第25项中说过?

时间:2018-01-21 15:54:40

标签: c++ string c++11

在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吗?

2 个答案:

答案 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);
}

此版本将避免创建临时。