我正在尝试实现一个固定大小的数组类,它将代表小尺寸的向量。我想定义典型的向量运算,例如乘以标量并与另一个向量求和。问题是我无法使用这两个代码获得相同的性能:
for (size_t i = 0; i < N; ++i)
vout[i] = (k[0][i] + 2*k[1][i] + 2*k[2][i] + k[3][i])/6;
// vs
vout = (k[0] + 2.0*k[1] + 2.0*k[2] + k[3])/6.0;
原因是第二个选项是在此过程中创建更多数组,而第一个选项是在原地添加。我想知道是否有一种方法可以编写一个对临时对象(r 值引用)进行操作的函数,以便在临时对象上执行求和,而无需分配额外的向量。
我当前的代码:
template<class T, int N>
class SVec {
public:
inline T& operator[](int i) { return mdata[i]; }
inline const T operator[](size_t i) const { return mdata[i]; }
inline T* data() { return mdata; }
inline T const* data() const { return mdata; }
inline SVec& operator+=(const SVec& rhs) {
for (size_t i = 0; i < N; ++i) mdata[i] += rhs.mdata[i];
return *this;
}
inline SVec& operator-=(const SVec& rhs) {
for (size_t i = 0; i < N; ++i) mdata[i] -= rhs.mdata[i];
return *this;
}
inline SVec& operator*=(T rhs) {
for (size_t i = 0; i < N; ++i) mdata[i] *= rhs;
return *this;
}
inline SVec& operator/=(T rhs) {
for (size_t i = 0; i < N; ++i) mdata[i] /= rhs;
return *this;
}
inline SVec& fma(const SVec& x, T y) {
for (size_t i = 0; i < N; ++i) mdata[i] += x[i]*y;
return *this;
}
inline SVec&& operator+(const SVec& rhs) && {
for (size_t i = 0; i < N; ++i) mdata[i] += rhs.mdata[i];
return std::move(*this);
}
inline SVec&& operator*(T rhs) && {
for (size_t i = 0; i < N; ++i) mdata[i] *= rhs;
return std::move(*this);
}
inline SVec&& operator/(T rhs) && {
for (size_t i = 0; i < N; ++i) mdata[i] /= rhs;
return std::move(*this);
}
private:
T mdata[N];
};
template<typename T, int N>
inline SVec<T, N> operator+(SVec<T, N> lhs, const SVec<T, N>& rhs) {
return lhs += rhs;
}
// Tried:
// template<typename T, int N>
// inline SVec<T, N>&& operator+(SVec<T, N>&& lhs, const SVec<T, N>& rhs) {
// lhs += rhs;
// return lhs;
// }
// template<typename T, int N>
// inline SVec<T, N>&& operator+(const SVec<T, N>& rhs, SVec<T, N>&& lhs) {
// lhs += rhs;
// return lhs;
// }
// template<typename T, int N>
// inline SVec<T, N>&& operator+(SVec<T, N>&& lhs, SVec<T, N>&& rhs) {
// lhs += rhs;
// return lhs;
// }
template<typename T, int N>
inline SVec<T, N> operator-(SVec<T, N> lhs, const SVec<T, N>& rhs) {
return lhs -= rhs;
}
template<typename T, int N>
inline SVec<T, N> operator*(SVec<T, N> lhs, T rhs) {
return lhs *= rhs;
}
tem
plate<typename T, int N>
inline SVec<T, N> operator*(T rhs, SVec<T, N> lhs) {
return lhs *= rhs;
}
template<typename T, int N>
inline SVec<T, N> operator/(SVec<T, N> lhs, T rhs) {
return lhs /= rhs;
}
template<typename T, int N>
inline SVec<T, N> operator/(T rhs, SVec<T, N> lhs) {
return lhs /= rhs;
}
template<typename T, int N>
inline SVec<T, N> fma(const SVec<T, N>& x, T y, SVec<T, N> z) {
return z.fma(x, y);
}
template<int N>
using DoubleVec = SVec<double, N>;