《Effective Modern C++》Item25中“无临时std::string对象”为何成立?
Let's start by clarifying what happens with the original two setName overloads you showed:
When you call
w.setName("Adela Novak"), the string literal"Adela Novak"is aconst char[]—not astd::string. Since neither of your original overloads accepts aconst char[]directly, the compiler has to create a temporarystd::stringto convert the literal into a type that matches theconst std::string¶meter. That's the temporary object you're expecting here.
Now, let's look at the universal reference version of setName, which would be written like this:
template<typename T> void setName(T&& newName) { name = std::forward<T>(newName); }
Here's the play-by-play of why no temporary is created:
- Type deduction magic: The compiler deduces
Tto be exactly the type of the string literal:const char[11](the 11 accounts for the 10 characters plus the null terminator). Thanks to C++'s reference collapsing rules,T&&ends up being an lvalue reference to that array (const char(&)[11]—string literals are lvalues, remember!). - Perfect forwarding preserves the type:
std::forward<T>(newName)keeps the original array type intact. When we assign this toname(thestd::stringmember), the array implicitly decays to aconst char*. - Direct assignment via
std::string's built-in overload:std::stringhas an assignment operator that takes aconst char*directly:std::string& operator=(const char* s). This operator builds the string's content straight from the C-style literal—no need to create an intermediate temporarystd::stringfirst.
In short, the universal reference version doesn't force the literal to be converted to a std::string upfront. Instead, it lets the std::string's own assignment logic handle the literal directly, cutting out the temporary object entirely.
内容的提问来源于stack exchange,提问作者foo

