我正在尝试遵循 Scott Meyers 在更有效 C++ 的第 22 项中的建议:“考虑使用op=
而不是独立op
”。他建议我们可以创建一个模板operator+
,这样所有实现的类都会operator+=
自动获得operator+
:
template<class T>
const T operator+(const T& lhs, const T& rhs)
{
return T(lhs) += rhs;
}
现在,在 Effective Modern C++ 的第 25 项中,有一个矩阵加法的示例(第 172 页),其中operator+
建议使用右值重载,因为如果您知道lhs
或者rhs
是右值,您可以使用它们来存储结果,防止可能是巨大矩阵的无用副本。所以我添加了重载:
template<class T>
T operator+(T&& lhs, const T& rhs)
{
return std::move(lhs += rhs);
}
template<class T>
T operator+(T const& lhs, T&& rhs)
{
return std::move(rhs += lhs);
}
template<class T>
T operator+(T&& lhs, T&& rhs)
{
return std::move(lhs += rhs);
}
这里的问题是它T&&
是一个通用引用,它最终会捕获所有内容,所以我最终从左值移动,这是不受欢迎的行为。
那么如何正确实现operator+
模板呢?
使用按值传递的部分解决方案:我还阅读了来自 Effective Modern C++ 的第 41 条:“考虑通过值传递可复制参数 ...”,因此我尝试编写自己的版本,如下所示:
template<class T>
const T operator-(T lhs, T rhs)
{
return lhs -= rhs;
}
但这错过了当 rhs 是右值时的优化机会,因为在这种情况下,我不会使用 rhs 来存储结果。所以这只是部分解决方案。