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

时间:2016-08-09 14:47:05

标签: c++ vector stl

我有一个std::vector std::vectors我希望使用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或更高版本的答案,你仍然可以为任何可能发现它有用的人写它。

2 个答案:

答案 0 :(得分:1)

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

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];
   }
}

答案 1 :(得分:1)

我建议在行主要配置中围绕单个std::vector创建一个包装器来表示您的矩阵,使其比2D std::vector更方便使用。以下应该与pre-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_;
};

然后使用您的示例推送新列很简单:

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

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