条款1 GotW#18: Iterators

以下程序至少有四个与iterator相关的问题:

int main()
{
	vector<Date> e;
	copy(istream_iterator<Date>(cin),
		 istream_iterator<Date>(),
		 back_inserter(e));
	vector<Date>::iterator first = 
		find(e.begin(),e.end(),"01/01/95");
	vector<Date>::iterator last = 
		find(e.begin(),e.end(),"12/31/95");
	*last = "12/30/95";
	copy(first,last,
		 ostream_iterator<Date>(cout,"\n"));
	e.insert(--end(),TodaysDate());
	copy(first,last,
		 ostream_iterator<Date>(cout,"\n"));
}

解答:

	vector<Date> e;
	copy(istream_iterator<Date>(cin),
		 istream_iterator<Date>(),
		 back_inserter(e));

目前为止一切都正确,Date class提供了一个输入操作符(>>),以便istream_iterator<Date>得以从cin stream读取Date资料。上述copy算法会把Date填充到vector内。

vector<Date>::iterator first = 
		find(e.begin(),e.end(),"01/01/95");
	vector<Date>::iterator last = 
		find(e.begin(),e.end(),"12/31/95");
	*last = "12/30/95";

错误:上述last可能不是有效迭代器,可能是e.end(),不能解引用一个e.end()。

	copy(first,last,
		 ostream_iterator<Date>(cout,"\n"));

错误,这可能是非法的,因为[first,last)可能不是有效范围;实际上,first可能在last之后。

e.insert(--end(),TodaysDate());

第一个错误:--end()可能是非法的,vector<Date>::iterator经常只是一个Date*,C++语言不允许修改内置类型的临时变量。下面代码也可能非法:

Date* f();//函数返回一个Date*
p = --f();//错误,但可以写成f()-1

幸运的是,vector<Date>::iterator是一个随机迭代器,因此编写如下的正确代码将不会有任何的损失:

e.insert(end()-1,TodaysDate());

第二个错误,如果end()为空,所有迭代器将是无效的迭代器。

copy(first,last,
		 ostream_iterator<Date>(cout,"\n"));
}

错误:first和last可能不是有效迭代器。

本例e.insert()操作的结果是vector可能增长也可能不增长,这意味着内存可能移动也可能不移动。由于这种不确定性,我们必须认为容器的任何已存在的迭代器都是可能无效的。这种情况下,如果内存确实移动了,那么这个问题copy()函数会发生难以诊断的core dump。

总结:

永远不要解引用无效迭代器。

使用迭代器时,注意四个主要问题:

  1. 有效值:迭代器可以解引用么?
  2. 有效生存期,使用迭代器时,仍然有效么?
  3. 有效范围:一对迭代器是一个有效范围么?first确实在last之前(或相等)吗?两个迭代器确实都指向同一容器的元素吗?
  4. 非法的内置类型操作:例如,是否由代码企图取修改内置类型的临时对象,正如上述的“--end()”。(幸运的是,编译器通常会捕捉这种错误的,对于指向类类型的(非内置类型))迭代器,为了语法方便,库的作者一般允许这样的操作。)

     

 

猜你喜欢

转载自blog.csdn.net/weixin_28712713/article/details/85156113