使用std::vector 创建矩阵类,如何在构造函数中设置std::vector 的大小?

问题描述

我正在创建一个名为“matrix”的类,它的类成员std::vector<std::vector<T>>,在类构造函数中设置其大小的最佳优化方法是什么?我在 matrix_.resize(m) 行的构造函数中使用 m,然后使用 for 循环设置其行值(矩阵 m x n)。我的问题是:

  1. 使用 .resize() 是一个方法吗?我听说它效率不高,但我想不出别的了

  2. 例如,当我使用 std::vector<std::vector<T>> = matrix_; 并使用 matrix_.resize(m) 时,matrix_ 现在将为“m”个 std::vector<T> 对象提供“m”个空格,但是,如果 matrix_ 不知道其对象的大小(std::vector<T>),它将如何管理内存?如果每个对象都是 size(1000) 或更大怎么办?

#include <iostream>
#include <vector>

// Matrix of shape m x n,'m' lines and 'n' columns
template <typename T>
class matrix {
private:
    typedef T value_type;
    typedef std::vector<value_type> row;
    std::vector<row> matrix_;
    
public:
    // Default constructor,initializes a matrix of size 1x1,with element 0.
    matrix() {
        matrix_.resize(1);
        row temp = {0};
        matrix_[0] = temp;
    };
    matrix(size_t m,size_t n) {
        matrix_.resize(m);
        // Appends 'm' rows to the matrix_
        for (size_t i = 0; i < m; i++) {
            row temp(n);    // Creates a row of 'n' columns
            matrix_[i] = temp;
        }
    }
    value_type& at (size_t m,size_t n) {
        return matrix_[m][n];
    }
};

int main() {
    matrix<double> first(2,2);
    first.at(0,0) = 3.3;
    first.at(0,1) = 5.2;
    first.at(1,0) = 8.9;
    first.at(1,1) = 1.4;

    return 0;
}

解决方法

最好的方法是不这样做。向量的向量是个坏主意,尤其是在小尺寸的情况下,因为您希望内存是连续的。

template <typename T>
class matrix {
public:
  typedef T value_type; // expose this
private:
  std::size_t m_size = 0;
  std::size_t n_size = 0
  std::vector<T> data;
public:
  // Default constructor,initializes a matrix of size 0
  matrix():matrix(0,0) {};
  // square matrix
  explicit matrix(std::size_t n):matrix(n,n) {};
  matrix(std::size_t m,std::size_t n):
    m_size(m),n_size(n),data(m*n,0)
  {}
  value_type& operator()(size_t m,size_t n) {
    return data[m*n_size + n];
  }
  value_type const& operator()(size_t m,size_t n) const {
    return data[m*n_size + n];
  }
};

添加 array_viewspan

template<class It>
struct range {
  It b,e;
  It begin()const{return b;}
  It end()const{return e;}
  std::size_t size()const{ return end()-begin(); }
  bool empty()const{ return begin()==end(); }
};
template<class T>
struct array_view:range<T*> {
  T& operator[](std::size_t i)const{
    return this->begin()[i];
  }
  array_view(T* start,T* finish):range<T*>{ start,finish }{}
  array_view():array_view(nullptr,nullptr){}
  array_view(T* start,std::size_t length):array_view( start,start+length ) {}
};

我们可以添加

   array_view<T> operator[](std::size_t m) {
     return {std::addressof(data[m*n_size]),n_size};
   }
   array_view<T const> operator[](std::size_t m) const {
     return {std::addressof(data[m*n_size]),n_size};
   }

您现在获得了高效的 matrix[a][b] 语法。 (addressof 只是我偏执。