有一个模板向量类(与容器无关,与数学相关),我需要重载常见的数学运算符。像这样重载有意义吗:
template <typename T, size_t D>
Vector<T, D> operator+(const Vector<T, D>& left, const Vector<T, D>& right)
{
std::cout << "operator+(&, &)" << std::endl;
Vector<T, D> result;
for (size_t i = 0; i < D; ++i)
result.data[i] = left.data[i] + right.data[i];
return result;
}
template <typename T, size_t D>
Vector<T, D>&& operator+(const Vector<T, D>& left, Vector<T, D>&& right)
{
std::cout << "operator+(&, &&)" << std::endl;
for (size_t i = 0; i < D; ++i)
right.data[i] += left.data[i];
return std::move(right);
}
template <typename T, size_t D>
Vector<T, D>&& operator+(Vector<T, D>&& left, const Vector<T, D>& right)
{
std::cout << "operator+(&&, &)" << std::endl;
for (size_t i = 0; i < D; ++i)
left.data[i] += right.data[i];
return std::move(left);
}
这段测试代码运行得很好:
auto v1 = math::Vector<int, 10>(1);
auto v2 = math::Vector<int, 10>(7);
auto v3 = v1 + v2;
printVector(v3);
auto v4 = v3 + math::Vector<int, 10>(2);
printVector(v4);
auto v5 = math::Vector<int, 10>(5) + v4;
printVector(v5);
// ambiguous overload
// auto v6 = math::Vector<int, 10>(100) + math::Vector<int, 10>(99);
并打印输出这个:
operator+(&, &)
8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
operator+(&, &&)
10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
operator+(&&, &)
15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
有两个右值引用的问题,但我认为这并不重要。
为什么我想这么做?因为出于性能原因,在理论上,不创建新对象会比较快,但是真的吗?也许编译器会优化使用operator+(const Vector& left,const Vector& right)
的简单代码,没有任何理由重载右值引用?
&&
与非模板函数中的&&
不同。在模板函数中,&&
是一个__转发引用__(并且适用于引用折叠规则);而在非模板函数中,&&
是一个右值引用,不进行折叠。你有转发引用。 - Richard Crittenfoo<T>
(就像这里一样)的情况下,它是一个真正的右值引用。 - MikeMBauto&& result = x + temporary();
,那么结果是一个悬空引用,因为它引用的临时对象已经失效。 - M.M