为什么矢量迭代器指向越界
Why does the vector iterator point out of bounds?
我正在研究一种递归合并排序算法,其中一个迭代器超出了界限。我确信我的问题的根源是我的算法有缺陷,但我花了好几天的时间来研究它,我只是没有看到我的失误。我不知道该往哪个方向走。能找一个比我更有经验/更聪明的人看看吗?(带有驱动程序的完整程序可在Github上获得。)
输出为:
before: 50 5 40 10 30 15 20 20 10 25
after : -1808873259 5 10 10 15 20 20 25 30 40 50
/* ^
* Extra recursive call, and out-of-bounds.
*/
需要明确的是,我只能返回类型为T的向量,在本例中为int,但我从这篇文章中知道,使用void函数更好。
template <typename T>
vector<T> mergesort(typename vector<T>::iterator begin, typename vector<T>::iterator end){
vector<T> newVector;
if (begin!=end){
vector<T> tmp1;
vector<T> tmp2;
typename vector<T>::iterator mid1 = begin;
typename vector<T>::iterator mid2 = begin;
long origDistance = distance(begin,end);
long endOfRange1 = origDistance/2;
long begOfRange2 = endOfRange1+1;
advance(mid1,endOfRange1);
advance(mid2,begOfRange2);
tmp1 = mergesort<T>(begin,mid1);
tmp2 = mergesort<T>(mid2,end);
//"merge()" is from the STL, link in comments.
merge(tmp1.begin(),tmp1.end(),tmp2.begin(),tmp2.end(), back_inserter(newVector));
} else {
newVector.push_back(*begin);
}
return newVector;
}
当begin == end
时取消引用begin
。这是未定义的行为。可能您想要if (origDistance == 1)
,然后push_back单个元素并返回。
如果end
指向向量的最后一个元素,那么函数看起来可以工作。然而,在你的示例程序中,你这样称呼它:
newVector = mergesort<int>(vec.begin(), vec.end());
vec.end()
指向矢量的末尾,它不指向最后一个元素。因此,您的函数会出错,因为它最终试图访问您传入的第二个迭代器所指向的元素
您可以调用您的函数,如:mergesort<int>(vec.begin(), vec.end() - 1);
。
然而,这会让其他阅读您代码的人感到惊讶。最好重写mergesort
函数以遵循正常的C++范围约定,也就是说,名为end
的参数应该超过末尾。mid1
应等于mid2
。
好吧-如果不弄清楚这一点,我就睡不着了,约翰·兹温克和M.M让我走上了正确的方向,这是得到正确输出的代码:
template <typename T>
vector<T> mergesort(typename vector<T>::iterator begin, typename vector<T>::iterator end){
vector<T> newVector;
long origDistance = distance(begin,end); /*Get distance first.*/
if (origDistance==1){ /*Added better anchor case checking for distance.*/
newVector.push_back(*begin);
return newVector;
}
vector<T> tmp1;
vector<T> tmp2;
typename vector<T>::iterator mid1 = begin;
typename vector<T>::iterator mid2 = begin;
long endOfRange1 = origDistance/2;
long begOfRange2 = endOfRange1;/*Edited from: endOfRange+1*/
advance(mid1,endOfRange1);
advance(mid2,begOfRange2);
tmp1 = mergesort<T>(begin,mid1);
tmp2 = mergesort<T>(mid2,end);
merge(tmp1.begin(),tmp1.end(),tmp2.begin(),tmp2.end(), back_inserter(newVector));
return newVector;
}
这里我将向您展示如何做到这一点。
template <typename T>
void mergesort(typename vector<T>::iterator, typename vector<T>::iterator);
// ...
mergesort<int>(vec.begin(), vec.end());
newVector = vec;
// ...
template <typename T>
void mergesort(typename vector<T>::iterator begin, typename vector<T>::iterator end){
auto const N = std::distance(begin, end);
if (N <= 1) return;
auto const middle = std::next(begin, N / 2);
mergesort<T>(begin, middle);
mergesort<T>(middle, end);
std::inplace_merge(begin, middle, end);
}
正确输出:
before: 50 5 40 10 30 15 20 20 10 25
after : 5 10 10 15 20 20 25 30 40 50
STL已经有了inplace_merge,为什么要重新实现它呢?有了这种方法,你就不必去想有什么难以逾越的界限。
相关文章:
- 使用std::multimap迭代器创建std::list
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++中带有List类的迭代器Segfault
- 如何在c++迭代器类型中包装std::chrono
- 集合上的输出迭代器:assign和increment迭代器
- Boost Spirit,获取迭代器内部语义动作
- 对于set上的循环-获取next元素迭代器
- 为什么output_editor Concept不需要output_e迭代器标记
- c++17文件系统::recursive_directory迭代器()在mac上没有给出这样的目录,但在windows上
- 使用迭代器时如何访问对象在向量中的位置?
- std::vector::迭代器是否可以合法地作为指针
- 跟随整数索引列表的自定义类迭代器
- 不明白迭代器,引用和指针失效,一个例子
- 我可以使用反向迭代器作为ForwardIt吗
- ESP8266单片机矢量迭代器的C++问题
- 如何在C++中将迭代器作为函数参数传递
- 是否应避免从非常量迭代器转换为常量迭代器?
- 如何在 c++ 中将字符串迭代器变量传递给函数?
- 自定义迭代器越界
- 为什么矢量迭代器指向越界