【问题标题】:Iterator operator ++ overloading C++迭代器运算符 ++ 重载 C++
【发布时间】:2020-06-14 15:01:19
【问题描述】:

我正在使用二维 std::vector 编写自定义类 Matrix。 所以问题是我需要为迭代器重载++操作,这样我就可以一次遍历整个矩阵。

template <typename T>
class Matrix {
private:
    std::vector<std::vector<T>> arr;

public:
    Matrix(const std::vector<std::vector<T>>& tmp) {
        arr = tmp;
    }
    std::pair<size_t, size_t> size() const {
        std::pair<size_t, size_t> tmp;
        if (arr.empty()) {
            tmp.first = 0;
            tmp.second = 0;
        } else {
            tmp.first = arr.size();
            tmp.second = arr[0].size();
        }
        return tmp;
    }
    T operator () (size_t i, size_t j) const {
        return arr[i][j];
    }
    Matrix& transpose() {
        std::vector<std::vector<T>> tmp(size().second, std::vector<T>(size().first));
        for (size_t i = 0; i < size().first; ++i) {
            for (size_t j = 0; j < size().second; ++j) {
                tmp[j][i] = arr[i][j];
            }
        }
        *this = Matrix(tmp);
        return *this;
    }
    Matrix transposed() const {
        std::vector<std::vector<T>> tmp(size().second, std::vector<T>(size().first));
        for (size_t i = 0; i < size().first; ++i) {
            for (size_t j = 0; j < size().second; ++j) {
                tmp[j][i] = arr[i][j];
            }
        }
        return Matrix(tmp);
    }
    typename std::vector<T>::iterator begin() {
        return arr[0].begin();
    }
    typename std::vector<T>::iterator end() {
        return arr[size().first-1].end();
    }
};

例如,使用矩阵 mat = {{1,2},{3,4}},应该可以:

vector<vector<int>> arr = {{1,2},{3,4}};
Matrix mar(arr);
auto it = mat.begin();
while (it != mat.end()) {
    cout << *it << " ";
}

输出应该是:

1 2 3 4 

您能帮我如何为std::vector 迭代器重载operator++()begin()end()

【问题讨论】:

  • 看起来您想创建自己的迭代器。如果您以前从未这样做过,这可能会有点棘手。这是一些info about iterators
  • 旁白:如果你的作业允许,考虑T operator[](std::pair&lt;size_t, size_t&gt;) const;(或T&amp;const T&amp;)而不是T operator () (size_t i, size_t j) const
  • 旁白:transpose()可以简化为*this = transposed(); return *this;

标签: c++ matrix vector iterator operator-overloading


【解决方案1】:

您将不能只使用 std::vector 返回的迭代器并更改其任何方法。如果您愿意,可以创建您自己的迭代器类(例如,在您的内部向量中包含两个迭代器),您的矩阵类将返回,并为它们实现相关方法。

【讨论】:

    【解决方案2】:

    我正在使用二维 std::vector 编写自定义类 Matrix。

    不要那样做。为什么?

    1. 您正在重新发明轮子。您的用例不太可能如此特殊,以至于没有现有的矩阵/线性代数库满足您的需求。
    2. 没有二维std::vectors;你的意思是,一个向量的向量(这是你的例子所具有的)。这通常会有点慢,此外 - 它的语义可能不是您想要的(例如,调整单个行大小的能力、分散在堆中的行存储等)

    您可能想考虑一下,例如,the Eigen library's matrix class

    【讨论】:

    • 我知道我在倒转轮子,但这是我的家务 :-(
    • “这通常会有点慢”。我认为std::vector&lt;std::vector&lt;T&gt;&gt; 是一种反模式。几乎没有充分的理由在 std::vector&lt;T&gt; 上使用它。
    • @IndianaKernick 最常见的原因是通过data[x][y] 可以非常方便地访问像网格一样的数据。不过我同意你的看法。作为一种折衷方案,在一个个人项目中,我使用一个普通数组来维护数据,并有一个指向每行开头的二级指针数组。当然,这种方法没有自动边界检查,但它非常高效。
    • @IndianaKernick:我同意。但是: 1. 我不确定 OP 知道什么是模式和反模式。 2.我不想苛刻,所以选择了含糊。 3.如果OP的工作主要在单行内,那也没那么糟糕。
    • @GoshkaLP:在这种情况下,请考虑询问您的老师/助教这是否是他们真正的意思,因为就像其他人建议的那样 - 这意味着您需要为您的类,如果你以前没有这样做过,这有点让人头疼。
    【解决方案3】:

    所以使用一维(听起来不正确)向量的决定是有效的。谢谢大家!

    #include <iostream>
    #include <utility>
    #include <vector>
    
    template <typename T>
    class Matrix {
    private:
        std::vector<T> arr;
        size_t m = 0;
        size_t n = 0;
    
    public:
        Matrix(const std::vector<std::vector<T>>& tmp) {
            for (const auto& row : tmp) {
                for (const auto& x : row) {
                    arr.push_back(x);
                }
            }
            if (!tmp.empty()) {
                m = tmp.size();
                n = tmp[0].size();
            }
        }
        std::pair<size_t, size_t> size() const {
            std::pair<size_t, size_t> tmp;
            tmp.first = m;
            tmp.second = n;
            return tmp;
        }
        T operator () (size_t i, size_t j) const {
            return arr[i * m + j];
        }
        Matrix transposed() const {
            std::vector<std::vector<T>> tmp(size().second, std::vector<T>(size().first));
            for (size_t i = 0; i < size().first; ++i) {
                for (size_t j = 0; j < size().second; ++j) {
                    tmp[j][i] = arr[i * m + j];
                }
            }
            return Matrix(tmp);
        }
        Matrix& transpose() {
            *this = transposed();
            return *this;
        }
        auto begin() {
            return arr.begin();
        }
        auto end() {
            return arr.end();
        }
        auto begin() const {
            return arr.begin();
        }
        auto end() const {
            return arr.end();
        }
    };
    template <typename T>
    std::ostream& operator<<(std::ostream& out, const Matrix<T>& m) {
        for (size_t i = 0; i < m.size().first; ++i) {
            for (size_t j = 0; j < m.size().second; ++j) {
                if (j == 0)
                    out << m(i, j);
                else
                    out << "\t" << m(i, j);
            }
            if (i != m.size().first - 1)
                out << "\n";
        }
        return out;
    }
    
    template <typename T>
    Matrix<T> operator + (const Matrix<T>& m1, const Matrix<T>& m2) {
        std::vector<std::vector<T>> tmp(m1.size().first, std::vector<T>(m1.size().second));
        for (size_t i = 0; i < m1.size().first; ++i) {
            for (size_t j = 0; j < m1.size().second; ++j) {
                tmp[i][j] = m1(i, j) + m2(i, j);
            }
        }
        return Matrix(tmp);
    }
    
    template <typename T>
    Matrix<T>& operator += (Matrix<T>& m1, const Matrix<T>& m2) {
        m1 = m1 + m2;
        return m1;
    }
    
    template <typename T1, typename T2>
    Matrix<T1> operator * (const Matrix<T1>& m, const T2& x) {
        std::vector<std::vector<T1>> tmp(m.size().first, std::vector<T1>(m.size().second));
        for (size_t i = 0; i < m.size().first; ++i) {
            for (size_t j = 0; j < m.size().second; ++j) {
                tmp[i][j] = m(i, j) * x;
            }
        }
        return Matrix(tmp);
    }
    
    template <typename T1, typename T2>
    Matrix<T1> operator * (const T2& x, const Matrix<T1>& m) {
        return m * x;
    }
    
    template <typename T1, typename T2>
    Matrix<T1>& operator *= (Matrix<T1>& m, const T2& x) {
        m = m * x;
        return m;
    }
    
    template <typename T>
    Matrix<T> operator * (const Matrix<T>& first, const Matrix<T>& second) {
        std::vector<std::vector<T>> tmp(first.size().first, std::vector<T>(second.size().second));
        T x = 0;
        for (size_t i = 0; i < first.size().first; ++i) {
            for (size_t j = 0; j < second.size().second; ++j) {
                for (size_t k = 0; k < first.size().second; ++k) {
                    x += first(i, k) * second(k, j);
                }
                tmp[i][j] = x;
                x = 0;
            }
        }
        return Matrix(tmp);
    }
    
    template <typename T>
    Matrix<T>& operator *= (Matrix<T>& first, const Matrix<T>& second) {
        first = first * second;
        return first;
    }
    
    

    【讨论】:

      猜你喜欢
      • 2022-01-10
      • 2011-10-18
      • 1970-01-01
      • 2021-07-09
      • 2011-12-07
      • 2013-09-07
      • 2017-02-22
      • 2012-03-12
      • 2016-02-03
      相关资源
      最近更新 更多