在项目 41 中,Scott Meyers 编写了以下两个类:
class Widget {
public:
void addName(const std::string& newName) // take lvalue;
{ names.push_back(newName); } // copy it
void addName(std::string&& newName) // take rvalue;
{ names.push_back(std::move(newName)); } // move it; ...
private:
std::vector<std::string> names;
};
class Widget {
public:
template<typename T> // take lvalues
void addName(T&& newName) // and rvalues;
{ // copy lvalues,
names.push_back(std::forward<T>(newName)); } // move rvalues;
} // ...
private:
std::vector<std::string> names;
};
评论中写的是正确的,即使它根本不意味着这两个解决方案是等价的,并且书中确实讨论了一些差异。
In the errata但是,作者评论了书中未讨论的另一个区别:
Another behavioral difference between (1) overloading for lvalues and rvalues and (2) a template taking a universal reference (uref) is that the lvalue overload declares its parameter
const
, while the uref approach doesn't. This means that functions invoked on the lvalue overload's parameter will always be theconst
versions, while functions invoked on the uref version's parameter will be theconst
versions only if the argument passed in isconst
. In other words, non-const
lvalue arguments may yield different behavior in the overloading design vis-a-vis the uref design.
但我不确定我是否理解它。
其实写这个问题我大概是明白了,但是我还是不太确定,所以不写答案。
可能作者是说当一个非const
左值传递给 addName
, newName
是const
在第一个代码中,非 const
在第二个代码中,这意味着 if newName
被传递给另一个函数(或在其上调用了一个成员函数),而不是该函数需要接受 const
。参数(或成为 const
成员函数)。
我的解释正确吗?
但是,我看不出这在具体示例中有何不同,因为在 newName
上没有调用任何成员函数。 , 也不会传递给对 (不完全是: const
具有不同重载的函数和非 const
参数std::vector<T>::push_back
有两个重载 const T&
arguments 和 T&&
arguments`,但左值仍然只绑定(bind)到前一个重载...)。
最佳答案
在第二种情况下,当一个 const std::string
左值传递给模板
template<typename T>
void addName(T&& newName)
{ names.push_back(std::forward<T>(newName)); }
实例化结果如下(我删除了 std::forward
调用,实际上是一个空操作)
void addName(const std::string& newName)
{ names.push_back(newName); }
而如果 std::string
传递左值,然后是 addName
的结果实例是
void addName(std::string& newName)
{ names.push_back(newName); }
这意味着非const
std::vector<>::push_back
的版本被称为。
在第一种情况下,当一个 std::string
左值传递给 addName
,无论 const
是什么,都会选择第一个重载 -ness
void addName(const std::string& newName)
{ names.push_back(newName); }
这意味着 const
过载 std::vector<>::push_back
在这两种情况下都被选中。
关于c++ - 了解勘误表中有关 EMC++ 第 41 项的评论,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65602182/