在第一维std::vector的std::vector中写入

Writting in a std::vector of std::vectors in the first dimension

本文关键字:std vector 一维      更新时间:2023-10-16

我有一个std::vectorsstd::vector,我想使用for循环将一个元素推回每个内部向量。代码看起来像这样,但显然不能工作,因为您不能以这种方式访问每个向量(matrix[i] =),并且第8行产生Segmentation Fault

std::vector<std::vector<float> > matrix;
for (size_t j = 0; j < number_of_columns; ++j) {
  vector<float> elements_to_push = compute_elements();
  for (size_t i = 0; i < number_of_rows; ++i) {
    matrix[i].push_back(elements_to_push[i]);
  }
}

所以,我想按列来写元素。对我来说,逐行编写不是一个选择,因为我需要使用一些期望元素按此顺序编写的外部函数。

我认为解决方案涉及使用指针向量(std::vector<float*>),但我想知道是否有可能只使用向量,因为这简化了事情。

此外,如果解决方案不涉及c++ 11或更高版本的功能,那将是最好的,因为我必须保持向后兼容性。但是,如果您有一个使用c++ 11或更高版本的答案,您仍然可以为其他可能觉得有用的人编写它。

如果计算和推入行而不是列会更容易。然而,这里有一个解决方案(因为你已经知道矩阵的大小):

std::vector<std::vector<float> > matrix(number_of_rows, std::vector<float>(number_of_columns, float()));
for (size_t j = 0; j < number_of_columns; ++j) {
   vector<float> elements_to_push = compute_elements();
   for (size_t i = 0; i < number_of_rows; ++i) {
       matrix[i][j] = elements_to_push[i];
   }
}

我建议在行主配置中围绕单个std::vector创建一个包装器来表示您的矩阵,使其比2D std::vector更方便使用。以下应该与c++11之前的版本兼容,这就是为什么我没有使用auto和其他一些c++11以后的功能…

template<typename Ty>
class matrix {
    // enables use of [][] on matrix objects
    class proxy_row_vector {
    public:
        proxy_row_vector(std::vector<Ty>& _vec, std::size_t cols, std::size_t row_ind)
            : vec(_vec), columns(cols), row_index(row_ind) {}
        const Ty& operator[](std::size_t col_ind) const {
            return vec[row_index*columns + col_ind];
        }
        Ty& operator[](std::size_t col_ind) {
            return vec[row_index*columns + col_ind];
        }
    private:
        std::vector<Ty>& vec;
        std::size_t row_index;
        std::size_t columns;
    };
public:
    // construct rows*cols matrix with default-inserted Ty instances
    explicit matrix(std::size_t rows, std::size_t cols)
        : mtx(rows*cols), rows_(rows), cols_(cols) {}
    std::size_t rows() const { return rows_; }
    std::size_t columns() const { return cols_; }
    // used for const [][] access
    proxy_row_vector operator[](std::size_t row_ind) const {
        return proxy_row_vector(mtx, cols_, row_ind);
    }
    // used for mutable [][] access
    proxy_row_vector operator[](std::size_t row_ind) {
        return proxy_row_vector(mtx, cols_, row_ind);
    }
    // insert a new row at the end
    void push_row(const std::vector<Ty>& row_vec) {
        for (std::vector<Ty>::iterator it = row_vec.begin(); it < row_vec.end(); ++it) 
            mtx.push_back(*it);
        ++rows_;
    }
    // insert a new column at the end
    void push_column(const std::vector<Ty>& col_vec) {
        insert_column(cols_, col_vec);
    }
    // insert a row at indicated position
    void insert_row(size_type row_pos, const std::vector<Ty>& row_vec) {
        mtx.insert(mtx.begin() + row_pos*cols_, row_vec.begin(), row_vec.end());
        ++rows_;
    }
    // insert a column at indicated position
    void insert_column(size_type col_pos, const std::vector<Ty>& col_vec) {
        for (std::size_t i = 0; i < col_vec.size(); ++i) {
            mtx.insert(mtx.begin() + i*(cols_+1)+col_pos,col_vec[i]);
        }
        ++cols_;
    }
private:
    std::vector<Ty> mtx;
    std::size_t rows_;
    std::size_t cols_;
};

那么push一个新列就很简单了,使用下面的例子:

matrix<float> mat;
std::vector<float> column_to_push = compute_elements();
mat.push_column(column_to_push);

注意:在上面的matrix类中,没有边界或大小检查,因为它是此类类的最小示例。您应该在行/列插入方法中添加大小检查,以避免尝试分别推入超过(或少于)当前矩阵的列数或行数的行向量或列向量。此外,你可能想添加迭代器支持(通过std::vector迭代器微不足道)和其他方法(例如擦除行/列)。