【发布时间】:2016-04-05 16:04:19
【问题描述】:
我正在开发带有自定义迭代器的通用二维容器。
现在我想为我的iterator 和constant_iterator 类型设置一个begin() 和一个end() 函数。
我的自定义迭代器在我的模板 Matrix 类中(但为了清楚起见,我将它们单独放在这里)。
template <class T>
class Matrix {
#pragma mark PUBLIC TYPEDEFS
public:
typedef T value_type;
typedef std::size_t size_type;
//typedef typename T::size_type size_type;
//typedef T::size_type size_type;
#pragma mark -
#pragma mark PRIVATE TYPEDEFS
private:
typedef T* pointer_type;
typedef T** storage_type;
#pragma mark -
#pragma mark PRIVATE VARIABLES
private:
size_type width_;
size_type height_;
storage_type data_;
// private iterators
Iterator<T*, T> m_iterator_;
Iterator<const T*, const T> m_const_iterator_;
H_Iterator<T*, T> m_hiterator_;
H_Iterator<const T*, const T> m_const_hiterator_;
#pragma mark -
#pragma mark PUBLIC VARIABLES & TYPEDEFS
public:
typedef Iterator<T*, T> iterator_type;
typedef Iterator<const T*, const T> const_iterator_type;
typedef H_Iterator<T*, T> hiterator;
typedef H_Iterator<const T*, const T> const_hiterator;
#pragma mark -
#pragma mark CONSTRUCTORS & DESTRUCTORS
public:
explicit Matrix(const std::string& fileName) {
}
Matrix(const size_type& width, const size_type& height) : width_(width),
height_(height),
data_(CreateMatrix(width, height)),
m_iterator_(*data_, width, height),
m_const_iterator_(*data_, width, height),
m_hiterator_(*data_, width, height),
m_const_hiterator_(*data_, width, height),
// fill the created matrix with default values of "T"
for (Matrix<T>::iterator_type it = this->begin(); it != this->end(); ++it)
*it = T();
}
~Matrix() {
delete [] data_[0]; // because in data_[0] is array of value_type
delete [] data_;
}
#pragma mark -
#pragma mark PRIVATE METHODS
private:
storage_type CreateMatrix(const size_type width, const size_type height) {
storage_type d = new pointer_type[height]; // array with pointers pointing to rows inside the "block"
pointer_type block = new value_type[width * height]; // one block of memory to store the data
for (size_type row = 0; row < height; ++row)
d[row] = &block[row * width];
return d;
}
#pragma mark -
#pragma mark PUBLIC METHODS
public:
hiterator h_begin(size_type row) { return m_hiterator_.begin(row); }
hiterator h_end(size_type row) { return m_hiterator_.end(row); }
const_hiterator ch_begin(size_type row) { return m_const_hiterator_.begin(row); }
const_hiterator ch_end(size_type row) { return m_const_hiterator_.end(row); }
而我的内部Iterator 类+ 派生H_Iterator 类(H_Iterator 类用于从左到右循环遍历一行矩阵)
#pragma mark ITERATOR CLASSES
template <typename P, typename V> // "P" - PointerType; "V" - ValueType
class Iterator : public std::iterator<std::forward_iterator_tag, T> {
protected:
P itData_;
size_type w_; // width of the matrix
size_type h_; // height of the matrix
public:
Iterator(P d, size_type width, size_type height) : itData_(d), w_(width), h_(height) { }
Iterator() { }
public:
V& operator*() const {
return *itData_;
}
Iterator<P, V>& operator++() {
++itData_;
return *this;
}
Iterator<P, V>& operator= (T value) {
*itData_ = value;
return *this;
}
P operator->() {
return itData_;
}
friend bool operator==(const Iterator& lhs, const Iterator& rhs) {
return !(lhs.itData_ != rhs.itData_);
}
friend bool operator!=(const Iterator& lhs, const Iterator& rhs) {
return !(lhs.itData_ == rhs.itData_);
}
Iterator<P, V> begin() { return Iterator<P, V>(itData_, w_, h_); }
Iterator<P, V> end() { return Iterator<P, V>(itData_ + w_ * h_, w_, h_); };
};
template <typename P, typename V> // "P" - PointerType; "V" - ValueType
class H_Iterator : public Iterator<P, V> {
public:
H_Iterator(P d, size_type width, size_type height) : Iterator<P, V>(d, width, height) { }
H_Iterator() { }
public:
H_Iterator<P, V> begin(size_type row) { return H_Iterator<P, V>(this->itData_ + this->w_ * row, this->w_, this->h_); }
H_Iterator<P, V> end(size_type row) { return H_Iterator<P, V>(this->itData_ + this->w_ * row + this->w_, this->w_, this->h_); };
};
目前,如果我想使用常量迭代器遍历其中一行,我必须这样做(=我必须使用专门为 constant_hiterator - ch_begin() 和 @ 制作的 begin 和 end 函数987654335@):
Matrix<int> m (5, 5);
for (Matrix<int>::const_hiterator hit = m.ch_begin(row); hit != m.ch_end(row); ++hit) {
cout << *hit << " ";
}
我的const_hiterator 和hiterator 都只有一个begin() 和end() 函数。所以我可以像 std::vector 的迭代器一样编写迭代器代码:
std::vector<int> vector;
for (std::vector<int>::const_iterator it = vector.begin(); it != vector.end(); ++it) { }
for (std::vector<int>::iterator it = vector.begin(); it != vector.end(); ++it) { }
我假设我应该在hiterator 和const_hiterator 之间进行某种类型的转换。
【问题讨论】:
-
旁注:没有稀疏矩阵,大小为 N*M 的一维数组使矩阵实现更容易。
-
另外,您应该首先正确设置矩阵类。 (析构函数肯定是错误的)
-
很抱歉,我不确定您的意思。我编辑了我的
Matrix类代码(添加了CreateMatrix()函数),所以如果这就是你的意思,你可以看到我如何在内存中表示我的数据。 -
忽略上面的cmets,但是你的内存模型太复杂了。删除行数组(storage_type),只剩下一个数组 N*M,也许还有一个运算符 T ()(size_type 行,size_type 列),没有运算符 []。
-
@Superian007 -- Dieter Lücking 指的是让您的矩阵在内部由大小为 N*M 的一维数组表示。这有许多优点。它确保数据紧凑且连续,这对于具有多个缓存级别的现代计算机非常有用,尤其是对于小型矩阵。它使您更容易对阵列进行切片和切块。对于多维数组,数据/视图模型(例如 Blitz++、Eigen)是比 STL 迭代器模型更好的方法。