最近在研究Effective Modern C++11和14
我浏览了本书第 171 页第 25 项的一部分,其中作者为 setName 函数提供了两个代码示例。
(1)
// Option 1, universal reference
class Widget {
public:
template<typename T>
void setName(T &&newName) // universal reference
{ name = std::move(newName); }// compiles, but is // bad, bad, bad!
//…
private:
std::string name;
std::shared_ptr<SomeDataStructure> p;
};
void main() {
Widget w;
w.setName("Adela Novak");
}
(2)
// Option 2, lvalue reference and rvalue reference
class Widget2 {
public:
void setName(const std::string &newName) { name = newName; }
void setName(std::string &&newName) { name = std::move(newName); }
//…
};
void main() {
Widget2 w;
w.setName("Adela Novak");
}
作者说:
随着 setName 的版本采用通用引用,字符串 文字“Adela Novak”将被传递给 setName,它会在哪里 传送给 w 内的 std::string 的赋值运算符。 w的 因此,名称数据成员将直接从字符串中分配 文字;不会出现临时 std::string 对象。
然而,对于 setName 的重载版本,一个临时的 std::string 对象将被创建用于 setName 的参数绑定 到,然后这个临时的 std::string 将被移动到 w 的数据中 成员。因此,对 setName 的调用将需要执行一个 std::string 构造函数(创建临时的),一个 std::string 移动赋值运算符(将 newName 移动到 w.name),以及一个 std::string 析构函数(销毁临时的)。
'''
如果我的理解是正确的,在选项 1 和选项 2 中,我们将在 main() 函数中隐式为“Adela Novak”创建一个临时 std::string 对象。
对于选项 1,我们将临时 std::string 对象发送到 setName(),然后 T&& 将被推断为右值,因为“Adela Novak”是右值。
因此,在选项 1 中,我们只创建一个临时的 std::string 对象。
对于选项 2,我们将临时 std::string 对象发送到 setName()。因为“Adela Novak”是右值,所以我们将选择右值重载 setName() 函数。但是,当我们要调用右值重载函数时,我们必须为 newName 显式创建另一个临时 std::string 对象。
因此,在选项 2 中,我们必须创建两个临时 std::string 对象。
我的问题是: