2

这是一个代码示例,使用std::reverse_iterator

template<typename T, size_t SIZE>
class Stack {
    T arr[SIZE];
    size_t pos = 0;
public:
    T pop() {
        return arr[--pos];
    }
    Stack& push(const T& t) {
        arr[pos++] = t;
        return *this;
    }
    auto begin() {
        return std::reverse_iterator(arr+pos);
    }
    auto end() {
        return std::reverse_iterator(arr);
                // ^ does reverse_iterator take this `one back`? how?
    }
};

int main() {
    Stack<int, 4> s;
    s.push(5).push(15).push(25).push(35);
    for(int val: s) {
        std::cout << val << ' ';
    }
}

// output is as expected: 35 25 15 5 

std::reverse_iterator用作另一个迭代器的适配器时,新适应的end应该是原始begin之前的一个。但是调用std::prev开始是UB

开始前怎么std::reverse_iterator办?

4

1 回答 1

4

从迭代器初始化std::reverse_iterator不会在初始化时减少迭代器,因为在向它发送begin时它将是 UB (不能假设这std::prev(begin)是一个有效的调用)。

诀窍很简单,std::reverse_iterator保留传递给它的原始迭代器,而不修改它。只有当它被取消引用时,它才会回看实际值。所以在某种程度上,迭代器指向内部的下一个元素,它可以从中获取当前元素。

它看起来像:

// partial possible implementation of reverse_iterator for demo purpose
template<typename Itr>
class reverse_iterator {
    Itr itr;
public:
    constexpr explicit reverse_iterator(Itr itr): itr(itr) {}

    constexpr auto& operator*() {
        return *std::prev(itr); // <== only here we peek back
    }
    constexpr auto& operator++() {
        --itr;
        return *this;
    }
    friend bool operator!=(reverse_iterator<Itr> a, reverse_iterator<Itr> b) {
        return a.itr != b.itr;
    }
};

然而,这是一个内部实现细节(实际上可以以其他类似方式实现)。的用户std::reverse_iterator不应关心它是如何实现的。

于 2021-05-21T10:55:00.477 回答