我有一个非常基本的2D C ++容器,它依赖于一维容器(std :: array或std :: vector)和“高级”索引。预计此容器不能存储很多元素,甚至不能存储500个元素。访问其元素的最佳方法是什么?
最初,我int
用于在迭代容器时直接为元素建立索引。然而,看完后一点,职位如这一个让我改用std::size_t
替代。(转换主要是为了养成良好的习惯,而不是出于容器的要求。但是其他消息源使我怀疑这是否真的是一种好习惯。)
结果,我不得不重新调整几个for()
循环以避免下溢引起的错误,例如,当检查彼此相邻的元素的值时,或者当元素在行或列中向后迭代时。这些更改继而降低了可读性,并使索引更易于出错。(我的经验绝对是这方面的一个因素。)
我该怎么办?
std::size_t
int
(同时还限制了2D存储空间的大小,以避免出现不太可能的溢出)先感谢您!
PS:甚至C ++ 20功能都受到欢迎!
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] 删除。
我来说两句