为什么在创建矩阵类时使用向量是不好的? [英] Why is it bad to use vectors when creating a matrix class?

查看:198
本文介绍了为什么在创建矩阵类时使用向量是不好的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于我的矩阵类,我做了:

  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 your operator[] return a proxy object (which you implement). The proxy will have its own operator[] 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆