Eigen SparseMatrix返回函数编译报错原因及修复方案咨询
Eigen稀疏矩阵列子集提取函数编译错误解决
可正常工作的返回式函数实现
Eigen::SparseMatrix<double> col_sp(const Eigen::SparseMatrix<double>& x, const std::vector<unsigned int>& index){ int n_cols = index.size(); Eigen::SparseMatrix<double> x_subset(x.rows(), n_cols); // 可选:提前预留非零元素空间,提升性能 x_subset.reserve(x.nonZeros()); for(int i=0; i!=n_cols; ++i){ // 将只读列表达式转换为临时SparseMatrix后赋值 x_subset.col(i) = Eigen::SparseMatrix<double>(x.col(index[i])); } // 可选:压缩矩阵,优化内存占用与后续操作效率 x_subset.makeCompressed(); return x_subset; }
报错原因
Eigen中SparseMatrix::col()返回的是只读稀疏块表达式(类型为SparseMatrixColXpr),它仅支持读取操作,不能作为左值直接接收赋值。你最初的代码中x_subset.col(i) = x.col(index[i])试图将只读表达式直接赋值给另一个稀疏列表达式,触发了Eigen的静态断言检查,抛出THIS_SPARSE_BLOCK_SUBEXPRESSION_IS_READ_ONLY错误。
你改用引用传入的版本能运行,是因为外部已经提前初始化了x_subset的正确尺寸与内存空间,但本质上这种写法依然存在风险,正确的赋值逻辑仍需要转换只读表达式为可赋值的完整稀疏矩阵对象。
未来规避方法
- 避免直接赋值稀疏块表达式:不要将
col()/row()返回的只读表达式直接赋值给另一个稀疏块,必须将右侧转换为完整的SparseMatrix临时对象,或者使用insert()方法逐个插入非零元素。 - 优化稀疏矩阵操作性能:提前调用
reserve()为非零元素分配内存,避免频繁内存重分配;操作完成后调用makeCompressed()压缩矩阵,减少内存占用并加速后续计算。 - 批量索引更高效实现:若需批量提取多列,可使用Eigen的向量索引直接切片(要求Eigen 3.4及以上版本支持),代码更简洁且性能更优:
Eigen::SparseMatrix<double> col_sp(const Eigen::SparseMatrix<double>& x, const std::vector<unsigned int>& index){ Eigen::VectorXi idx_vec(index.size()); for(int i=0; i<index.size(); ++i) idx_vec(i) = index[i]; return x(Eigen::all, idx_vec); }
内容的提问来源于stack exchange,提问作者doro
相关产品推荐
相关产品推荐

