是否存在std::view类工具提取第n个元素?如何轻量访问矩阵类的行?
问题
假设我有一个类矩阵结构,定义如下(注:原代码中的vector<T,M>应为笔误,实际应为std::array<T,M>,否则维度定义不符合矩阵列存储逻辑):
union { std::array<T, M * N> m_x; std::array<std::array<T, M>, N> m_col; };
我希望访问该结构的第i行,要求能将该行的begin和end迭代器传递给其他函数,且实现是轻量级(无计算开销)的。比如在矩阵乘法场景中,需要计算第i行第j列的元素(内积),要把第一个矩阵的第i行和第二个矩阵的第j列传递给std::transform(std::execution::par_unseq, ...)。我可以用boost::counting_iterator,但希望仅依赖C++标准库实现。
解决方案
1. 直接使用原生指针(最简零开销方案)
std::array的底层是连续内存,m_x作为大小为M*N的一维数组,第i行的起始位置就是m_x.data() + i*N,末尾位置是m_x.data() + (i+1)*N。原生指针本身就是标准的随机访问迭代器,完全满足std::transform等算法的要求,没有任何额外开销:
// 获取第i行的起始和结束迭代器(指针) auto row_begin = m_x.data() + i * N; auto row_end = row_begin + N;
直接将这两个指针传入算法即可,这是最直接高效的实现方式。
2. 自定义轻量级迭代器(语义化封装)
如果需要更具语义的迭代器(而非直接暴露指针),可以实现一个极简的随机访问迭代器,内部仅持有指针,所有操作直接转发给指针,编译器会完全优化掉封装层,同样零开销:
template<typename T> class RowIterator { public: // 迭代器必备的类型别名 using value_type = T; using pointer = T*; using reference = T&; using difference_type = std::ptrdiff_t; using iterator_category = std::random_access_iterator_tag; // 构造函数 constexpr RowIterator(pointer ptr) : m_ptr(ptr) {} // 解引用操作 constexpr reference operator*() const { return *m_ptr; } constexpr pointer operator->() const { return m_ptr; } constexpr reference operator[](difference_type n) const { return m_ptr[n]; } // 自增/自减 constexpr RowIterator& operator++() { ++m_ptr; return *this; } constexpr RowIterator operator++(int) { auto tmp = *this; ++m_ptr; return tmp; } constexpr RowIterator& operator--() { --m_ptr; return *this; } constexpr RowIterator operator--(int) { auto tmp = *this; --m_ptr; return tmp; } // 加减运算 constexpr RowIterator& operator+=(difference_type n) { m_ptr += n; return *this; } constexpr RowIterator operator+(difference_type n) const { return RowIterator(m_ptr + n); } constexpr RowIterator& operator-=(difference_type n) { m_ptr -= n; return *this; } constexpr RowIterator operator-(difference_type n) const { return RowIterator(m_ptr - n); } // 差值计算 constexpr difference_type operator-(const RowIterator& other) const { return m_ptr - other.m_ptr; } // 比较操作 constexpr bool operator==(const RowIterator& other) const { return m_ptr == other.m_ptr; } constexpr bool operator!=(const RowIterator& other) const { return m_ptr != other.m_ptr; } constexpr bool operator<(const RowIterator& other) const { return m_ptr < other.m_ptr; } constexpr bool operator<=(const RowIterator& other) const { return m_ptr <= other.m_ptr; } constexpr bool operator>(const RowIterator& other) const { return m_ptr > other.m_ptr; } constexpr bool operator>=(const RowIterator& other) const { return m_ptr >= other.m_ptr; } private: pointer m_ptr; };
使用方式:
RowIterator<T> row_begin(m_x.data() + i*N); RowIterator<T> row_end(row_begin + N);
3. 矩阵乘法场景的实际应用
以计算矩阵A第i行与矩阵B第j列的内积为例,直接用指针方案的代码如下:
T dot_product = 0; std::transform(std::execution::par_unseq, A.m_x.data() + i*N, A.m_x.data() + (i+1)*N, B.m_col[j].data(), std::back_inserter(dot_product), [](T a, T b) { return a*b; });
这里B.m_col[j]是列存储的std::array<T,M>,直接通过data()获取起始指针即可,和行迭代器完美配合。
内容的提问来源于stack exchange,提问作者0xbadf00d
相关产品推荐
相关产品推荐

