范围for循环
集合类数据类型的基本操作之一就是迭代遍历并处理集合中的每个元素。
C++
提供了范围for循环语句实现这个操作(从头到尾依次遍历元素)。
一个可用于范围for循环(可迭代)语句的类必须满足以下条件:
(1)
实现begin()
方法。获取指向第一个元素的迭代器或指针。
(2)
实现end()
方法。获取指向最后一个元素的下一个元素的迭代器或指针。
(3)
begin()
和end()
的返回值支持++
操作。
std::vector<int> vi = { 0, 1, 2, 3, 4, ,5, 6, 7, 8, 9 };
for (auto x : vi) {
std::cout << x << std::endl;
}
等价于
for (auto it = vi.begin(); it != vi.end(); ++it) {
std::cout << *it << std::endl;
}
Iterable
介于迭代器类比较复杂,先用指针来说明这个问题。
iterable.h
#ifndef ITERABLE_H
#define ITERABLE_H
template <typename Item>
class Iterable {
public:
virtual Item *begin() = 0;
virtual Item *end() = 0;
};
#endif
原始指针类型的变量一定是可以做++
运算的。
如此一来,凡是公有继承Iterable
的非抽象类都可用在范围for循环语句上。
可迭代栈
使用FixStack
公有继承Iterable
,实现一个可迭代的栈。
实现
fix_stack.h
#ifndef FIX_STACK
#define FIX_STACK
#include <cstddef>
#include "iterable.h"
template <typename Item>
class FixStack : public Iterable<Item> {
public:
FixStack(size_t cap);
~FixStack();
Item *begin() override;
Item *end() override;
void Push(const Item &item);
Item Pop();
bool IsEmpty() const;
size_t Size() const;
private:
void ReSize(size_t max);
size_t cap_;
size_t sz_;
Item *data_;
};
template <typename Item>
FixStack<Item>::FixStack(size_t cap) : cap_(cap), sz_(0)
{
data_ = new Item[cap_];
}
template <typename Item>
FixStack<Item>::~FixStack()
{
delete[] data_;
data_ = nullptr;
}
template <typename Item>
Item *FixStack<Item>::begin()
{
return data_;
}
template <typename Item>
Item *FixStack<Item>::end()
{
return data_ + sz_;
}
template <typename Item>
void FixStack<Item>::ReSize(size_t max)
{
Item *newData = new Item[max];
for (size_t i = 0; i < sz_; ++i) {
newData[i] = data_[i];
}
data_ = newData;
cap_ = max;
}
template <typename Item>
void FixStack<Item>::Push(const Item &item)
{
if (sz_ == cap_) {
ReSize( 2 * cap_);
}
data_[sz_++] = item;
}
template <typename Item>
Item FixStack<Item>::Pop()
{
return data_[--sz_];
}
template <typename Item>
bool FixStack<Item>::IsEmpty() const
{
return sz_ == 0;
}
template <typename Item>
size_t FixStack<Item>::Size() const
{
return sz_;
}
#endif
测试
void FixStackTest2()
{
FixStack<std::string> st(1);
std::string str;
while (std::cin >> str) {
st.Push(str);
}
for (auto x : st) {
std::cout << x << std::endl;
}
}
运行
int main()
{
FixStackTest2();
return 0;
}
运行结果: