如何用带索引的标准库函数替代迭代器?Eigen::VectorXd调用std::partial_sum方案
在Eigen::VectorXd上实现前缀和的几种方案
嘿,这个问题我之前也踩过坑!Eigen确实没给VectorXd这类稠密向量提供标准STL迭代器,但完全不用自己手动写索引循环,有几个更优雅高效的办法:
1. 优先用Eigen原生的cumsum()方法(最推荐)
Eigen的Array模块自带了前缀和实现cumsum(),而VectorXd可以非常方便地转成ArrayXd来使用,用完再转回Vector就行——而且这个方法是Eigen优化过的,性能比STL的std::partial_sum还要好(毕竟Eigen会做向量化加速)。
示例代码:
#include <Eigen/Dense> #include <iostream> int main() { Eigen::VectorXd vec(5); vec << 1, 2, 3, 4, 5; // 转成Array调用cumsum,再转回Vector Eigen::VectorXd partial_sum = vec.array().cumsum(); std::cout << partial_sum << std::endl; // 输出结果:1, 3, 6, 10, 15 return 0; }
如果需要原地修改向量,直接vec = vec.array().cumsum();就行,非常简洁。
2. 自己实现极简索引迭代器(适配STL算法)
如果你一定要用std::partial_sum,可以写一个轻量的索引式迭代器包装Eigen向量。这个迭代器基于索引操作,满足STL随机访问迭代器的要求,完全能适配std::partial_sum这类算法。
示例迭代器实现+用法:
#include <Eigen/Dense> #include <numeric> #include <iostream> template<typename VectorType> struct EigenVectorIterator { // STL迭代器必备的类型定义 using value_type = typename VectorType::Scalar; using reference = value_type&; using pointer = value_type*; using difference_type = std::ptrdiff_t; using iterator_category = std::random_access_iterator_tag; EigenVectorIterator(VectorType& vec, Eigen::Index idx) : vec_(&vec), idx_(idx) {} // 解引用操作 reference operator*() { return (*vec_)(idx_); } pointer operator->() { return &(*vec_)(idx_); } // 自增自减 EigenVectorIterator& operator++() { ++idx_; return *this; } EigenVectorIterator operator++(int) { auto temp = *this; ++idx_; return temp; } EigenVectorIterator& operator--() { --idx_; return *this; } EigenVectorIterator operator--(int) { auto temp = *this; --idx_; return temp; } // 加减偏移 EigenVectorIterator operator+(difference_type n) const { return EigenVectorIterator(*vec_, idx_ + n); } EigenVectorIterator operator-(difference_type n) const { return EigenVectorIterator(*vec_, idx_ - n); } difference_type operator-(const EigenVectorIterator& other) const { return idx_ - other.idx_; } // 比较运算符 bool operator==(const EigenVectorIterator& other) const { return vec_ == other.vec_ && idx_ == other.idx_; } bool operator!=(const EigenVectorIterator& other) const { return !(*this == other); } bool operator<(const EigenVectorIterator& other) const { return idx_ < other.idx_; } }; int main() { Eigen::VectorXd vec(5); vec << 1, 2, 3, 4, 5; Eigen::VectorXd result(vec.size()); std::partial_sum( EigenVectorIterator(vec, 0), EigenVectorIterator(vec, vec.size()), EigenVectorIterator(result, 0) ); std::cout << result << std::endl; return 0; }
这个迭代器很简单,只实现了std::partial_sum需要的核心操作,你可以根据需求扩展其他运算符。
额外说明:为什么Eigen不提供STL迭代器?
Eigen的核心设计是表达式模板,它会在编译期优化整个计算流程(比如向量化、避免临时变量)。而STL迭代器是基于逐元素访问的模式,会破坏这种优化链条,所以Eigen更推荐用它自己的成员方法来完成这类操作——这也是为什么第一个方案是最优解的原因。
内容的提问来源于stack exchange,提问作者philx_x
相关产品推荐
相关产品推荐

