【C++】范围for循环原理深入理解

6 篇文章 0 订阅

目录

1. 语法定义

2. 测试代码

3. 执行流程解释

4. 等效旧标准代码


1. 语法定义

C++11新增范围for语法

for (declaration : exporession)
	statement
exporession:定义序列对象,即包含 begin()/end(),以及对应迭代器
declaration:定义一个变量,其类型可以是序列成员,也可以是通过序列成员转换获得

for (auto item : v)
	statement

按书上解释,其等同于

for (auto item = v.begin(), end = v.end(); beg != end; ++beg)
	statement

但二者在item类型上,有本质的区别,经实验,其语法应等效于

{ //< 加{},确保创建的是临时变量
	auto beg = v.begin(), end = v.end();
	for (decltype(*v.begin()) item; beg != end && (item = *beg, true); ++beg)
        statement
}

因此,item的类型是实际容器元素的类型,且可以使用功能 const auto & 进行变化,避免拷贝。

2. 测试代码

class IntVector;
class Iter
{
private:
	int _pos;
	const IntVector* _p_vec;

public:
	Iter(const IntVector* p_vec, int pos)
		: _pos(pos), _p_vec(p_vec)
	{
		std::cout << __FUNCTION__ << std::endl;
	}

	bool operator!=(const Iter& other) const
	{
		std::cout << __FUNCTION__ << std::endl;
		return _pos != other._pos;
	}
	int operator*() const;
	const Iter& operator++()
	{
		std::cout << __FUNCTION__ << std::endl;
		++_pos;
		return *this;
	}
};

class IntVector
{
private:
	int _data[100] = { 0 };

public:
	IntVector() {}

	int get(int col) const
	{
		std::cout << __FUNCTION__ << std::endl;
		return _data[col];
	}

	Iter begin() const
	{
		std::cout << __FUNCTION__ << std::endl;
		return Iter(this, 0);
	}

	Iter end() const
	{
		std::cout << __FUNCTION__ << std::endl;
		return Iter(this, 100);
	}

	void set(int index, int val)
	{
		std::cout << __FUNCTION__ << std::endl;
		_data[index] = val;
	}
};

int Iter::operator*() const
{
	std::cout << __FUNCTION__ << std::endl;
	return _p_vec->get(_pos);
}

int main()
{
	IntVector vct;
	int i = 0;
	for (const auto& it : vct)
	{
		printf("===========\r\n");
		printf("%d\r\n", it);
		
		//! 设置循环两遍
		if ((++i) == 2)
		{
			break;
		}
	}

	system("pause");
	return 0;
}

打印结果

IntVector::begin
Iter::Iter
IntVector::end
Iter::Iter
Iter::operator !=
Iter::operator *
IntVector::get
===========
0
Iter::operator ++
Iter::operator !=
Iter::operator *
IntVector::get
===========
0
请按任意键继续. . .

3. 执行流程解释

第一遍循环,需要创建循环用的变量

IntVector::begin        ——1.beg = vct.begin()
Iter::Iter                     ——2.beg 构造函数
IntVector::end           ——3.end = vct.end()
Iter::Iter                     ——4.end 构造函数

Iter::operator !=         ——5.beg != end
Iter::operator *           ——6.item = *beg
IntVector::get             ——7.*beg,调用容器,获取元素

第二遍循环,更新beg和item

Iter::operator ++        ——1.++beg
Iter::operator !=         ——2.beg != end
Iter::operator *          ——3.item = *beg
IntVector::get            ——4.*beg,调用容器,获取元素

4. 等效旧标准代码

{
	int i = 0;
	IntVector v;
	auto beg = v.begin(), end = v.end();
	for (decltype(*v.begin()) item; beg != end && (item = *beg, true); ++beg)
	{
		printf("===========\r\n");
		printf("%d\r\n", item);

		//! 设置循环两遍
		if ((++i) == 2)
		{
			break;
		}
	}
}

判断语句,增加 (item = *beg, true),使item的赋值,在beg!=end判定通过后执行,避免异常。

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

求知向道

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值