【问题标题】:Creating a matrix class with std::vector, how to set the size of std::vector in the constructor?用std::vector创建矩阵类,如何在构造函数中设置std::vector的大小?
【发布时间】:2021-04-01 16:37:17
【问题描述】:

我正在创建一个名为“matrix”的类,其类成员为std::vector<std::vector<T>>,在类构造函数中设置其大小的最佳优化方法是什么?我在m 行的构造函数中使用matrix_.resize(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>)?如果每个对象的大小(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;
}

【问题讨论】:

  • 不要使用二维向量。使用大小为 N x M 的一维向量,然后使用数学将 m 和 n 转换为单个索引,如下所示:stackoverflow.com/questions/2151084/…
  • 1.你不需要resize,因为你可以在vector的构造函数中这样做,但它没有太大的危害。
  • 2.只是作为一维vector?我真的没有得到你的关心。
  • 是的,顶层vector负责管理m其他vector。那些m 向量都完全能够处理它们自己的n 标量元素。但无论如何你都应该使用一个平面 n*m 向量。
  • fwiw,sizeof( std::vector&lt;T&gt;) 是一个常数,无论向量包含多少元素。元素不存储在向量中,但它们是动态分配的

标签: c++ matrix data-structures c++14


【解决方案1】:

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

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_view或span:

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 只是我偏执)。

【讨论】:

  • 我今天和你学到了一些东西,谢谢!我不知道我可以使用非默认构造函数创建默认构造函数。但为什么matrix():matrix(0,0) {}; 上的:?只是语法还是可以使用 = ? std::addressof 究竟做了什么?谢谢!
  • @oucal 这些是成员初始化列表(与 std 初始化列表完全不同)。 = 不允许在那里。我会开始en.cppreference.com/w/cpp/language/constructor——也是谷歌标准地址; &amp; 涵盖了泛型代码中的偏执问题。
猜你喜欢
  • 2012-07-10
  • 2020-10-05
  • 1970-01-01
  • 1970-01-01
  • 2014-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-08
相关资源
最近更新 更多