为什么在创建矩阵类时使用向量是不好的? [英] Why is it bad to use vectors when creating a matrix class?
问题描述
对于我的矩阵类,我做了:
template< typename T,std :: uint32_t Height,std :: uint32_t宽度>
class Matrix
{
private:
std :: array< std :: array< T,Width> Height>元素;
static_assert(std :: is_arithmetic< T> :: value,参数T必须是算术类型。
public:
Matrix();
Matrix(T * Data);
Matrix(T ** Data);
Matrix(T Data [Height] [Width]);
Matrix(const std :: array< std :: array< T,Width> Height>& Data);
inline int size(){return Width * Height;}
inline const int size()const {return Width * Height;}
){return Width;}
inline const int height()返回宽度;}
inline const int width() const {return Height;}
std :: array< T,Width>& operator [](int Index);
const std :: array< T,Width>& operator [](int Index)const;
Matrix& operator =(const Matrix& M);
Matrix& operator +(const Matrix& M);
Matrix& operator - (const Matrix& M);
Matrix& operator *(const Matrix& M);
};
template< typename T,std :: uint32_t Height,std :: uint32_t Width>
Matrix< T,Height,Width> :: Matrix(){std :: memset(& Elements,0,sizeof(T)* Width * Height);}
template< typename T,std :: uint32_t Height,std :: uint32_t Width>
Matrix< T,Height,Width> :: Matrix(T * Data){if(Data)std :: memcpy(& Elements,Data,sizeof(T)* Width * Height);}
template< typename T,std :: uint32_t Height,std :: uint32_t Width>
Matrix< T,Height,Width> :: Matrix(T ** Data){if(Data)std :: memcpy(& Elements,& Data [0] [0],sizeof宽度*高度);}
模板< typename T,std :: uint32_t Height,std :: uint32_t Width>
Matrix< T,Height,Width> :: Matrix(T Data [Height] [Width]){std :: memcpy(& Elements,& Data [0] [0],sizeof宽度*高度);}
模板< typename T,std :: uint32_t Height,std :: uint32_t Width>
Matrix< T,Height,Width> :: Matrix(const std :: array< std :: array< T,Width> Height>& Data){std :: memcpy(& Elements,&数据[0] [0],sizeof(T)*宽度*高度);}
template< typename T,std :: uint32_t Height,std :: uint32_t Width>
std :: array< T,Width>&矩阵< T,高度,宽度> ::运算符[](int索引){return Elements [索引];}
模板< typename T,std :: uint32_t Height,std :: uint32_t Width>
const std :: array< T,Width>& Matrix
因为我在线阅读并且许多评论说不使用向量,而是使用数组或使用std :: valarray ..
现在原因'm要求是因为我想重写我的矩阵类,所以我不必继续这样做:
Matrix< Type,Width,Height>
我宁愿在构造函数中做一次,而不必为每个单个函数输入。如上所述。例如,我必须为每个函数AND写出每个Matrix参数的长模板声明。 ALso我不知道如何删除向量的调整大小/推后,以便当用户索引向量时,他们将无法调整大小,所以我使用数组。
我将使用一个1D数组并将其索引(I * Width + J),但后来我丢失了[] []运算符。
坏的使用矢量的矢量?任何想法,以提高我的类,并保持它RAII符合?我不太明白如何使用valarray和上面是烦人维护。任何想法是赞赏。
解决方案真的矢量的向量不是最好的方法。假设数据是矩形的(不是锯齿状的),通过向量矢量方法进行的分配中存在一些低效率,更何况它防止了一些常见的重塑操作(将我的2×3矩阵视为3×2或6×1,复制)。
我将使用一个1D数组并索引它(I * Width + J) [] []运算符。
当然,使用一维向量。那很棒。然后你可以调整它的大小,重塑它,等等,并具有接近最佳性能的许多操作。
但你不想失去双下标的能力(
[x] [y]
)?好。只需让你的运算符[]
返回一个代理对象(你实现)。代理将有自己的operator []
,它将在第二个轴上运行。也就是说,第一个[]
将返回一个轻量级的对象,它只是足以实现第二个[]
。 / p>For my matrix class, I did:
template<typename T, std::uint32_t Height, std::uint32_t Width> class Matrix { private: std::array<std::array<T, Width>, Height> Elements; static_assert(std::is_arithmetic<T>::value, "Argument T must be of arithmetic type."); public: Matrix(); Matrix(T* Data); Matrix(T** Data); Matrix(T Data[Height][Width]); Matrix(const std::array<std::array<T, Width>, Height> &Data); inline int size() {return Width * Height;} inline const int size() const {return Width * Height;} inline int width() {return Width;} inline const int width() const {return Width;} inline int height() {return Height;} inline const int height() const {return Height;} std::array<T, Width>& operator[](int Index); const std::array<T, Width>& operator[](int Index) const; Matrix& operator = (const Matrix &M); Matrix& operator + (const Matrix &M); Matrix& operator - (const Matrix &M); Matrix& operator * (const Matrix &M); }; template<typename T, std::uint32_t Height, std::uint32_t Width> Matrix<T, Height, Width>::Matrix() {std::memset(&Elements, 0, sizeof(T) * Width * Height);} template<typename T, std::uint32_t Height, std::uint32_t Width> Matrix<T, Height, Width>::Matrix(T* Data) {if (Data) std::memcpy(&Elements, Data, sizeof(T) * Width * Height);} template<typename T, std::uint32_t Height, std::uint32_t Width> Matrix<T, Height, Width>::Matrix(T** Data) {if (Data) std::memcpy(&Elements, &Data[0][0], sizeof(T) * Width * Height);} template<typename T, std::uint32_t Height, std::uint32_t Width> Matrix<T, Height, Width>::Matrix(T Data[Height][Width]) {std::memcpy(&Elements, &Data[0][0], sizeof(T) * Width * Height);} template<typename T, std::uint32_t Height, std::uint32_t Width> Matrix<T, Height, Width>::Matrix(const std::array<std::array<T, Width>, Height> &Data) {std::memcpy(&Elements, &Data[0][0], sizeof(T) * Width * Height);} template<typename T, std::uint32_t Height, std::uint32_t Width> std::array<T, Width>& Matrix<T, Height, Width>::operator[](int Index) {return Elements[Index];} template<typename T, std::uint32_t Height, std::uint32_t Width> const std::array<T, Width>& Matrix<T, Height, Width>::operator[](int Index) const {return Elements[Index];}
because I read online and many comments saying not to use vectors and to instead use an array OR use std::valarray..
Now the reason I'm asking is because I want to re-write my matrix class so that I don't have to keep doing:
Matrix<Type, Width, Height>
every time.. I'd rather do that once in the constructor and not have to type that out for every single function.. As above. For example, I have to write out that long template declaration for each function AND for each Matrix argument. ALso I was not sure how to remove the resize/pushback for the vector so that when the user indexes the vector, they won't be able to resize it so I used arrays.I was going to use a 1D array and index it doing (I * Width + J) but then I lose my [][] operator.
Is it bad to use vector of vectors? Any ideas to improve my class and keep it RAII conformant? I don't quite understand how to use valarray and the above is annoying to maintain. Any ideas are appreciated.
解决方案It's true that a vector of vectors is not the best approach. Assuming the data is rectangular (not jagged), there is some inefficiency in the allocations done by the vector-of-vectors approach, not to mention it prevents the somewhat common "reshape" operation ("treat my 2x3 matrix as 3x2 or 6x1 without copying").
I was going to use a 1D array and index it doing (I * Width + J) but then I lose my [][] operator.
Sure, use a 1D vector. That's great. Then you can resize it, reshape it, etc., and have near-optimal performance for many operations. And you keep RAII.
But you don't want to lose the ability to double-subscript (
[x][y]
)? OK. Just make youroperator[]
return a proxy object (which you implement). The proxy will have its ownoperator[]
which will operate on the second axis. That is, the first[]
will return a lightweight object which knows just enough to implement the second[]
.这篇关于为什么在创建矩阵类时使用向量是不好的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!