Consider the following function:
Widget f(Widget w) {
   return w;
}
Supposing that Widget implements both copy and move constructors, according to the C++ standard, w has to be treated as a rvalue object in the return statement, in case the compiler would not consider copy elision a better alternative.
On the other hand, consider the version below:
Widget f(Widget&& w) {
   return w;
}
As opposite to the first version, according to Item 25 of Effective Modern C++, the author seems to be implying that returning w would certainly invoke the copy constructor. In other words, he suggests to return std::move(w) instead, in order to make the compiler use the (possibly faster) move constructor.
Can you explain why the second version of f() taking a Widget&& as argument is not equivalent to the first version taking a Widget by value with respect to the constructor being called in the return statement, also considering that in the body of both the functions the expression w refers to an lvalue?
Complete example demonstrating the behavior:
#include <iostream>
struct Widget
{
  Widget() { std::cout << "constructed" << std::endl; }
  ~Widget() { std::cout << "destructed" << std::endl; }
  Widget(const Widget&) { std::cout << "copy-constructed" << std::endl; }
  Widget(Widget&&) { std::cout << "move-constructed" << std::endl; }
};
Widget
f1(Widget w)
{
  return w;
}
Widget
f2(Widget&& w)
{
  return w;
}
int
main()
{
  f1(Widget {});
  std::cout << std::endl;
  f2(Widget {});
}
Output:
constructed
move-constructed
destructed
destructed
constructed
copy-constructed
destructed
destructed
 
    