访问自定义2维C ++容器元素的最佳方法

Dudly01

我有一个非常基本的2D C ++容器,它依赖于一维容器(std :: array或std :: vector)和“高级”索引。预计此容器不能存储很多元素,甚至不能存储500个元素。访问其元素的最佳方法是什么?

最初,我int用于在迭代容器时直接为元素建立索引。然而,看完后一点,职位如这一个让我改用std::size_t替代。(转换主要是为了养成良好的习惯,而不是出于容器的要求。但是其他消息源使我怀疑这是否真的是一种好习惯。)

结果,我不得不重新调整几个for()循环以避免下溢引起的错误,例如,当检查彼此相邻的元素的值时,或者当元素在行或列中向后迭代时。这些更改继而降低了可读性,并使索引更易于出错。(我的经验绝对是这方面的一个因素。)

我该怎么办?

  1. 坚持 std::size_t
  2. 继续使用int(同时还限制了2D存储空间的大小,以避免出现不太可能的溢出)
  3. 通过为列和行创建循环来坚持基于范围或迭代器的循环(欢迎使用建议和链接)
  4. 其他的东西

先感谢您!

PS:甚至C ++ 20功能都受到欢迎!

Yakk-亚当·内夫罗蒙特

std::ptrdiff_t是签名的std::size_t

我用那个 我听说过该标准应使用的论点,但要付出一点最大的代价。

编写跨步友好的迭代器有点麻烦。这是一个草图:

template<class T, class Stride=std::integral_constant<std::size_t, 1>>
struct stride_iterator {
  using difference_type = std::ptrdiff_t;
  using value_type = T;
  using reference= T&;
private:
  T* dataptr = nullptr;
  Stride datastride = {};
  T* data() const { return dataptr; }
  T*& data() { return dataptr; }
  Stride stride() const { return datastride; }
public:
  explicit stride_iterator( T* ptr, Stride s ):
    dataptr(ptr),
    datastride{ std::move(s) }
  {}
  explicit stride_iterator( T* ptr ):
    dataptr(ptr)
  {}
  stride_iterator():stride_iterator(nullptr) {}
  stride_iterator(stride_iterator const&)=default;
  stride_iterator& operator=(stride_iterator const&)& =default;
  stride_iterator(stride_iterator &&)=default;
  stride_iterator& operator=(stride_iterator &&)& =default;
  
  T& operator*() const { return *data(); }
  T* operator->() const { return data(); }
  T& operator[](std::ptrdiff_t n) const {
    return *(*this+n);
  }
  stride_iterator& operator+=( std::ptrdiff_t n )& {
    data() += (n*stride());
    return *this;
  }
  stride_iterator& operator-=( std::ptrdiff_t n )& {
    data() -= (n*stride());
    return *this;
  }
  friend stride_iterator operator+( std::ptrdiff_t rhs, stride_iterator lhs ) {
    return std::move(lhs)+rhs;
  }
  friend stride_iterator operator+( stride_iterator lhs, std::ptrdiff_t rhs ) {
    lhs += rhs; 
    return lhs;
  }
  friend stride_iterator operator-( stride_iterator lhs, std::ptrdiff_t rhs ) {
    lhs += rhs; 
    return lhs;
  }
  stride_iterator& operator++() {
    *this += 1;
    return *this;
  }
  stride_iterator& operator--() {
    *this -= 1;
    return *this;
  }
  stride_iterator operator++(int) {
    auto r = *this;
    ++*this;
    return r;
  }
  stride_iterator operator--(int) {
    auto r = *this;
    --*this;
    return r;
  }
  friend std::ptrdiff_t operator-( stride_iterator const& lhs, stride_iterator const& rhs ) {
    return (lhs.data()-rhs.data())/stride();
  }
  friend bool operator<( stride_iterator const& lhs, stride_iterator const& rhs ) {
    return lhs.data() < rhs.data();
  }
  friend bool operator<=( stride_iterator const& lhs, stride_iterator const& rhs ) {
    return lhs.data() <= rhs.data();
  }
  friend bool operator>( stride_iterator const& lhs, stride_iterator const& rhs ) {
    return lhs.data() > rhs.data();
  }
  friend bool operator>=( stride_iterator const& lhs, stride_iterator const& rhs ) {
    return lhs.data() >= rhs.data();
  }
  friend bool operator==( stride_iterator const& lhs, stride_iterator const& rhs ) {
    return lhs.data() == rhs.data();
  }
  friend bool operator!=( stride_iterator const& lhs, stride_iterator const& rhs ) {
    return lhs.data() != rhs.data();
  }
};

template<class It>
struct range {
    It b, e;
    It begin() const { return b; }
    It end() const { return e; }
    decltype(auto) operator[]( std::ptrdiff_t i ) const {
        return b[i];
    }
    std::size_t size() const { return end()-begin(); }
    bool empty() const { return end()==begin(); }
};


struct toy_matrix {
    std::ptrdiff_t width = 1;
    std::ptrdiff_t height = 1;
    std::vector<int> data = std::vector<int>( 1 );
    
    toy_matrix() = default;
    toy_matrix( std::size_t w, std::size_t h ):width(w),height(h), data(w*h) {}
    toy_matrix( std::size_t w, std::size_t h, std::initializer_list<int> il ):width(w),height(h), data(il) {
        data.resize(w*h);
    }
    
    range<stride_iterator<int>> row( std::ptrdiff_t i ) {
        int* ptr = data.data();
        ptr += height * i;
        return { stride_iterator<int>{ ptr }, stride_iterator<int>{ ptr + width } };
    }
    range<stride_iterator<int, std::ptrdiff_t>> column( std::ptrdiff_t i ) {
        int* ptr = data.data();
        ptr += i;
        return { stride_iterator<int, std::ptrdiff_t>{ ptr, width }, stride_iterator<int, std::ptrdiff_t>{ ptr + height * width, width } };
    }
    range<stride_iterator<int>> operator[]( std::ptrdiff_t i ) {
        return row(i);
    }
    int& operator()( std::ptrdiff_t x, std::ptrdiff_t y ) {
        return (*this)[x][y];
    }
};

测试代码:

toy_matrix m{ 5, 4, {
    1,2,3,4,5,
    10,20,30,40,50,
    100,200,300,400,500,
    1000,2000,3000,4000,5000,
}};

for (auto x : m.column(0)) {
    std::cout << x << "\n";
}
for (auto x : m.column(1)) {
    std::cout << x << "\n";
}
for (auto x : m.column(2)) {
    std::cout << x << "\n";
}

输出:

1
10
100
1000
2
20
200
2000
3
30
300
3000

现场例子

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

C#访问自定义链表对象的元素

来自分类Dev

C#访问自定义链表对象的元素

来自分类Dev

在C ++中复制大型容器的最佳方法

来自分类Dev

如何访问自定义元素的主机

来自分类Dev

如何访问自定义元素的主机

来自分类Dev

访问自定义元素的子节点?

来自分类Dev

访问嵌套的Polymer自定义元素中的JavaScript方法

来自分类Dev

没有阴影DOM的自定义元素:获取元素的最佳方法

来自分类Dev

访问模型中的自定义方法

来自分类Dev

自定义Magento 2容器/横幅

来自分类Dev

C ++自定义容器传递{}列表

来自分类Dev

在Javascript中按自定义顺序放置数组元素的最佳方法

来自分类Dev

如何在自定义 Ng2 表单元素中访问 NgFormControl

来自分类Dev

编写自定义异常的最佳方法

来自分类Dev

自定义动作栏的最佳方法

来自分类Dev

编写自定义异常的最佳方法

来自分类Dev

解析自定义Filtersyntax的最佳方法

来自分类Dev

创建自定义查找的最佳方法

来自分类Dev

存储自定义对象(Swift 中的类)以供 Objective-C 方法访问

来自分类Dev

如何从回调访问Polymer自定义元素

来自分类Dev

如何访问Knockout组件中的自定义元素?

来自分类Dev

如何从Polymer模板中访问自定义元素的主体?

来自分类Dev

如何从回调访问Polymer自定义元素

来自分类Dev

访问Haskell中的自定义类型变量的元素?

来自分类Dev

如何访问自定义单元元素

来自分类Dev

Haskell:访问自定义列表类型的元素

来自分类Dev

如何访问插槽内的自定义元素的 light dom?

来自分类Dev

访问自定义元素中的子对象

来自分类Dev

如何为Orchard Layout创建自定义容器元素?

Related 相关文章

热门标签

归档