构造和操作2d数组的最佳现代c ++方法是什么

时间:2018-10-29 03:41:35

标签: c++ arrays c++11 stl

正如标题中所述,我找到了大量解决方案。大多数人会说std::array<4, std::array<4, int>>std::vector<std::vector<int>>是好的,但是我发现这看起来很混乱,很难扩展到多维数组。另外,我担心这些数组实际上是对象数组,可能会带来一些开销(我想是这样,不是很确定)。那么最好的方法是什么?

3 个答案:

答案 0 :(得分:3)

一些要点让您入门。

首先,std::arraystd::vector。这很容易。如果您在编译时知道2d数组的大小,则可以肯定std::array否则std::vector

std::vector<std::vector<T>>可以满足需要快速准备的事情,并且很少在对性能不重要的代码中很少使用(1)

std::vector<std::vector<T>>的最大缺点是内存布局。您有两次间接访问,并且每行都是单独分配的,这对缓存造成了严重破坏,因此在性能关键代码(1)中绝对是不行的。对于性能至关重要的代码,您需要使用成熟的数学库。专家可以比您或我更好地编写面向性能的代码,并且这种库的另一个重要优点是它通过了时间的考验。

如果出于任何原因要自己编写此代码,则解决方案是将矩阵展平。即使用std::vector<T>(numRows * numColumns),然后使用以下公式访问元素:(i, j) -> v[i * numColumns + j]。并将其包装在一个不错的界面中。界面的复杂程度以及您允许对其进行哪种操作完全取决于您。


(1)我想指出,大多数情况下,尤其是新手程序员完全误解了性能问题(由于缺乏经验,这是完全可以理解的)。首先,有一些普遍适用的实践适用于任何情况。然后是对算法和所用数据类型的分析。但是除此之外,您首先编写代码以提高可读性,然后,如果考虑到性能,则对代码进行概要分析,并开始优化概要分析器告诉您的位置。

答案 1 :(得分:2)

我碰巧有这个未经测试的示例。如果可行,那么很好,否则它是如何在2D数组上创建1D视图的一个示例:

template<typename T>
class two_dee_array
{
public:
    two_dee_array(std::size_t row, std::size_t col)
        : v(row * col), stride(col) {}

    T& operator()(std::size_t row, std::size_t col)
        { return v[(row * stride) + col]; }

    T const& operator()(std::size_t row, std::size_t col) const
        { return v[(row * stride) + col]; }

    std::size_t col_size() const { return stride; }
    std::size_t row_size() const { return v.size() / stride; }

    auto begin() { return std::begin(v); }
    auto end() { return std::end(v); }

    auto begin() const { return std::begin(v); }
    auto end() const { return std::end(v); }

    auto cbegin() const { return std::cbegin(v); }
    auto cend() const { return std::cend(v); }

private:
    std::vector<T> v;
    std::size_t stride;
};

答案 2 :(得分:0)

使用多维数组时,首先想到的是Matrix。我将显示Matrix的{​​{1}} classes的3个变体。在前两种情况下,您将看到数据存储在一维数组中,但是基于2D转换进行索引。在第三种类型中,我仅使用一个templates来保存所有内容,但是我使用另一个std::vector<Type>来保存所有用于索引到高维矩阵的每个维度的步幅。

第1个 st std::vector<size_t>:-这将执行任何MxM - Matrix

Square Matrix

第2 nd template<class T, unsigned M> class Matrix { static const unsigned Stride = M; static const Size = Stride * Stride; T data[Size] = {}; public: Matrix() {}; Matrix( const T* dataIn ) { fillMatrix( dataIn ); } void fillMatrix( const T* dataIn ); void printMatrix(); }; template<class T, unsigned M> void Matrix<T,M>::fillMatrix( const T* dataIn ) { for ( unsigned int i = 0; i < Size; i++ ) { this->data[i] = dataIn[i]; } } template<class T, unsigned M> void Matrix<T,M>::printMatrix() { for ( unsigned int i = 0; i < Stride; i++ ) { for ( unsigned int j = 0; j < Stride; j++ ) { std::cout << this->data[i*Stride + j] << " "; } std::cout << '\n'; } } :-这将执行任何2D矩阵

MxN - Matrix

第3个 rd template<class T, unsigned M, unsigned N> class Matrix { private: static const unsigned Row = M; static const unsigned Col = N; static const unsigned Size = M * N; T data[Size] = {}; public: Matrix() {}; Matrix( const T* dataIn ) { fillMatrix( dataIn ); } void fillMatrix( const T* dataIn ); void printMatrix(); }; template<class T, unsigned M, unsigned N> void Matrix<T,M,N>::fillMatrix( const T* dataIn ) { for( unsigned int i = 0; i < Size; i++ ) { this->data[i] = dataIn[i]; } } template<class T, unsigned M, unsigned N> void Matrix<T,M,N>::printMatrix() { for( unsigned int i = 0; i < Row; i++ ) { for( unsigned int j = 0; j < Col; j++ ) { std::cout << this->data[i*Col + j] << " "; } std::cout << '\n'; } } :它将执行任何MxNx... - Matrix注意-这需要具有支持可变参数模板的编译器的现代C ++!看起来像这样。前两个将编译,您可以按原样使用。至于 这个;我没有展示整个课程,因为这只是冰山一角。我喜欢称其为体积矩阵的功能非常强大,并且有太多源可在此处发布,并且我的某些功能尚未完成。它还依赖于其他几个帮助程序类模板,并使用各种其他类型的类模板,这些类模板均与矩阵特别相关,以进行存储,记录等。但是它的基本外壳看起来像这样:

Arbitrary Matrix

它几乎完成的头文件看起来像这样,因为它仍在进行中,并且仅说明矩阵的实际存储情况:我仍然需要处理它的任何template<typename Type, size_t... Dims> class Matrix { public: static const size_t numDims_ = sizeof...(Dims); private: size_t numElements_; std::vector<Type> elements_; std::vector<size_t> strides_; public: Matrix() noexcept; template<typename... Arg> Matrix( Arg&&... as ) noexcept; const Type& operator[]( size_t idx ) const; size_t numElements() const { return elements_.size(); } const std::vector<size_t>& strides() const { return strides_; } const std::vector<Type>& elements() const { return elements_; } }; // Matrix 方面。

calculation