指向数组部分的指针。重载 [] 运算符以访问数组的各个部分

Posted

技术标签:

【中文标题】指向数组部分的指针。重载 [] 运算符以访问数组的各个部分【英文标题】:Pointer to portions of array. Overloading [] operator to access portions of array 【发布时间】:2021-10-25 14:51:16 【问题描述】:

根据Pointer to portions of array 中的问题,提出了一种对数组部分进行操作的结构。

我想就这一期提出进一步的问题。

我想使用 std::vector 为 blockMatrices 创建一个结构,并且需要更改结构的实现以从 4x4 矩阵中获取 3x3 矩阵。

当前的测试用例是:

#include <vector>
#include <array>
#include <iostream>

// define matrix 4x4
typedef std::array<double, 16> matrix4;

// define matrix 3x3
typedef std::array<double, 9>  matrix3;

// get 3x3 matrix out of a 4x4 matrix
struct subMat

    matrix4& matrix_;

    const double& operator[](size_t index) const
    
        static size_t mapping[] = 0, 1, 2, 4, 5, 6, 8, 9, 10;
        return matrix_[mapping[index]];
        
    subMat (matrix4& A): matrix_(A)
;

template <typename T>
double sum_of_elements(const T& arr)

    double res = 0;
    for (int i=0;i < 9; ++i)
    
        res += arr[i];
     
    return res;


int main(int argCount, char *args[])

    std::vector<matrix4> myBlockMatrix(5);

    for (int i=0; i < myBlockMatrix.size(); i++)
    
        for (int j = 0; j<myBlockMatrix[0].size(); j++)
        
            myBlockMatrix[i][j] = i*j;
        
    

    for (int i = 0; i<myBlockMatrix.size(); i++)
    
        std::cout << sum_of_elements(subMat(myBlockMatrix[i])) << std::endl; // this works
    

    subBlockMatrix subBlock (myBlockMatrix);
    for (int i = 0; i<myBlockMatrix.size(); i++)
    
        std::cout << sum_of_elements(subBlock[i])) << std::endl; 
     

    return 0;

为了重载[] 运算符,我有:

struct subBlockMatrix : std::vector<matrix4>

    std::vector<matrix4>& blockMatrix_;

    const matrix4& operator[](std::size_t index) const
       
        static size_t mapping[] = 0, 1, 2, 4, 5, 6, 8, 9, 10;
        return blockMatrix_[mapping[index]];
     
    subBlockMatrix(std::vector<matrix4>& A) : blockMatrix_(A) 
;

但这不起作用... 我很难理解如何使它工作,非常感谢您的帮助!

最好的问候

【问题讨论】:

继承可疑。 “但这不起作用……”?意思是说?编译问题(这是错误消息),错误行为(这是预期结果和当前结果)。 @Jarod42,我可以回答。第二个和第三个 for 循环的结果应该是相同的(应该是相同的索引):0、45、90、135、180。但是输出值是:0、36、72、108、144跨度> 使用return blockMatrix_[mapping[index]];,您可以更改向量的访问权限,而不是matrix4(您可能需要subMat operator[](std::size_t index) const return subMat(blockMatrix_[index]); )。 【参考方案1】:

我会从矩阵视图开始,它从数组视图开始。

#include <vector>
#include <iostream>

template<class T, class Size=std::size_t, class Stride=Size>
struct array_view 
  array_view( T* start, Size sz, Stride s ):
    b(start), length(sz), stride(s) 
  array_view( T* start, Size sz =  ):
    b(start), length(sz), stride(sz) 
  array_view() = default;
  array_view( T* start, T* finish ):
    array_view(start, finish-start) 
 
  T* begin() const  return b; 
  T* end() const  return b+length; 
  std::size_t size() const  return length; 
  bool empty() const  return size() == 0; 
  explicit operator bool() const  return b; 

  T& operator[]( std::size_t i ) const  return begin()[i]; 

  array_view& operator++() 
    *this += 1;
    return *this;
  
  array_view operator++(int)& 
    auto self = *this;
    ++this;
    return self;
  
  array_view& operator--() 
    *this -= 1;
    return *this;
  
  array_view operator--(int)& 
    auto self = *this;
    --this;
    return self;
  

  array_view& operator+=(std::ptrdiff_t delta)&
    b+=delta*length;
    return *this;
  
  array_view& operator-=(std::ptrdiff_t delta)&
    b-=delta*length;
    return *this;
  
  friend array_view operator+(array_view self, std::ptrdiff_t delta) 
    self += delta;
    return self;
  
  friend array_view operator-(array_view self, std::ptrdiff_t delta) 
    self -= delta;
    return self;
  
  friend array_view operator+(std::ptrdiff_t delta, array_view self) 
    self += delta;
    return self;
  
  friend array_view operator-(std::ptrdiff_t delta, array_view self) 
    self -= delta;
    return self;
  

  // checks address, not contents
  friend bool operator==(array_view const& lhs, array_view const& rhs) 
    return lhs.b == rhs.b && lhs.length == rhs.length && lhs.stride == rhs.stride;
  
  friend bool operator!=(array_view const& lhs, array_view const& rhs) 
    return !(lhs==rhs);
  
private:
  T* b = nullptr;
  Size length = ;
  Stride stride = ;
;

然后我们得到一个matrix_view。首先,我们编写一个index_iterator 用于迭代器包装器,该包装器是一个值(如一系列行或列,或一个整数):

template<class V>
struct index_iterator 
  index_iterator(V v):value(v) 

  V const& operator*() const&  return value; 
  V& operator*()&  return value; 
  V operator*()&&  return std::move(value); 

  V* operator->()  return std::addressof(value);  
  V const* operator->() const  return std::addressof(value); 

  friend bool operator==(index_iterator const& lhs, index_iterator const& rhs ) 
    return lhs.value==rhs.value;
  
  friend bool operator!=(index_iterator const& lhs, index_iterator const& rhs ) 
    return lhs.value!=rhs.value;
  

  index_iterator& operator++() 
    ++value;
    return *this;
  
  index_iterator operator++(int)& 
    auto self = *this;
    ++value;
    return self;
  
  index_iterator& operator--() 
    --value;
    return *this;
  
  index_iterator operator--(int)& 
    auto self = *this;
    --value;
    return self;
  

  index_iterator& operator+=( std::ptrdiff_t delta )& 
    value += delta;
    return *this;
  
  index_iterator& operator-=( std::ptrdiff_t delta )& 
    value -= delta;
    return *this;
  
  friend index_iterator operator+(index_iterator self, std::ptrdiff_t delta) 
    self += delta;
    return self;
  
  friend index_iterator operator-(index_iterator self, std::ptrdiff_t delta) 
    self -= delta;
    return self;
  
  friend index_iterator operator+(std::ptrdiff_t delta, index_iterator self) 
    self += delta;
    return self;
  
  friend index_iterator operator-(std::ptrdiff_t delta, index_iterator self) 
    self -= delta;
    return self;
  

  V operator[](std::size_t i)const 
    return *((*this) + i);
  
private:
  V value = ;
;

template<class T, class M=std::size_t, class Stride=M, class N=M>
struct matrix_view 
  using row_view = array_view<T, N, Stride>;

  matrix_view( T* start, M cols=, Stride stride = , N rows= ):
    b(start), m(cols), s(stride), n(rows)
  
  matrix_view() = default;
 
  index_iterator<row_view> begin() const  return b, n, s; 
  index_iterator<row_view> end() const  return begin()+m; 
  std::size_t size() const  return m; 
  bool empty() const  return size() == 0; 
  explicit operator bool() const  return b; 

  row_view operator[]( std::size_t i ) const  return begin()[i]; 
  
private:
  T* b = nullptr;
  M m = ;
  Stride s = ;
  N n = ;
;
template<std::size_t N>
using size = std::integral_constant<std::size_t, N>;


int main()
  std::vector<int> v 00,01,02,03, 10,11,12,13, 20,21,22,23, 30,31,32,33;
  matrix_view<int, size<3>, size<4>> m = v.data()+5;
  for (auto col:m) 
    for (auto e:col) 
      std::cout << e << ",";
    
    std::cout << "\n";
  

然后用一些 CRTP DRY 和 EBO 清理它。

但那只是我。

Live example.

【讨论】:

以上是关于指向数组部分的指针。重载 [] 运算符以访问数组的各个部分的主要内容,如果未能解决你的问题,请参考以下文章

Problem D: 整型数组运算符重载

指向数组部分的指针。过滤数组的操作

C++ 重载运算符 [ ][ ]

C语言之指针学习

指针与数组

重载加法运算符以添加两个多项式