在完成C++ Primer Plus(第五版)的习题5.17时发生的bug,困扰好一会。通过网上寻找解决办法,还是懵懂,翻回原书终于找到原因。其实也就是学的还是不够扎实,忽略很多细节。
题目要求:编写一段程序,检测两个vector<int>对象是否有一个是另一个的前缀。
编写的函数:
int main5_17()
{
int temp;
vector<int> ivec1={ 0,1, 1, 2 }, ivec2 = { 0, 1, 1, 2, 3, 5, 8 };
if (ivec1 < ivec2)
{
auto it1 = ivec1.cbegin(), it2 = ivec2.cbegin();
for (; it1 != ivec1.cend() || *it1 != *it2; it1++, it2++)
{
;
}
if (it1 == ivec1.cend())
{
cout << "ivec1是ivec2的前缀" << endl;
return 0;
}
}
else if (ivec1 > ivec2)
{
auto it1 = ivec1.cbegin(), it2 = ivec2.cbegin();
for (; it2 != ivec2.cend() || *it1 != *it2; it1++, it2++)
{
;
}
if (it2 == ivec2.cend())
{
cout << "ivec2是ivec1的前缀" << endl;
return 0;
}
}
cout << "没有前缀的对象存在" << endl;
return 0;
}
Bug:
can't dereference out of range vector iterator
Debug:
测试时发现在执行到for循环时出错,刚开始debug时以为是递增部分出的问题,迭代器后移之后条件语句解引用出错,但尝试之后发现并不是递增。其实也不应该第一个考虑到递增而应该时解引用部分。
条件语句本意是判断短的对象迭代是否到尾后元素,或者当两个解引用得到的元素不相等时就退出,但是实际编写的逻辑和思考的逻辑并没有一致(被第二个(!=)和第一个判断,常用的(!=)干扰到了逻辑运算)
按照思考的逻辑,应该修改成:
it2 != ivec2.cend() || *it1 != *it2
或者应该考虑到第一个常用的不等于比较运算符,中间的逻辑运算符改成(&&):
it2 != ivec2.cend() && *it1 != *it2
而翻回原书4.3的逻辑和关系运算符一节,短路求值时:
**对于逻辑与运算符,当且仅当左侧运算对象为真时才对右侧运算对象求值
**对于逻辑或运算符,当且仅当左侧运算对象为假时才对右侧运算对象求值
在印象中把逻辑或的求值搞混了,使用或的时候,迭代器递增到尾后元素时,`it1 != Ivec1.cend()`为假,于是对右侧运算对象求值,此时(*it1)显然已经超出vector对象的范围,非法访问了。