错误来源于,用
fs::directory_iterator iter(folderPath), end;
然后for循环
for (; iter != iter_end; ++iter) {}
最开始没问题,后来说加个进度条,统计一下所有文件数量,用了std::distance,
int totalFiles = std::distance(iter, iter_end);std::cout << " totalFiles is " << totalFiles << std::endl;
for (; iter != iter_end; ++iter) {}
奇怪的事情发生了
明明统计得到几百个文件,可是for循环一次都不动。
写了个测试代码:
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <boost/filesystem.hpp>namespace fs = boost::filesystem;
int main() {std::vector<int> numbers = {1, 2, 3, 4, 5};// 创建迭代器auto beginIter = numbers.begin();auto endIter = numbers.end();// 计算距离std::cout <<"iter == iter_end? " << (beginIter == endIter) <<std::endl;std::ptrdiff_t dist = std::distance(beginIter, endIter);std::cout <<"iter == iter_end? " << (beginIter == endIter) <<std::endl;std::cout << "距离: " << dist << std::endl;std::cout << "*beginIter : " << *beginIter << std::endl;fs::directory_iterator iter("/home/hqw"), end;std::cout <<"iter == iter_end? " << (iter == end) <<std::endl;std::ptrdiff_t dist2 = std::distance(iter, end);std::cout <<"iter == iter_end? " << (iter == end) <<std::endl;std::cout << "距离: " << dist2 << std::endl;return 0;
}
iter == iter_end? 0
iter == iter_end? 0
距离: 5
*beginIter : 1
距离: 5
iter == iter_end? 0
iter == iter_end? 1
距离: 101
通过输出结果可知,默认情况std::distance()不会去操作迭代器beginIter的,beginIter在原位,但是遇到boost的filesystem::directory_iterator迭代器(不确定是否全boost如此),他把我迭代器给“用掉”了,想想也可以理解,迭代器不是平铺的数据,想得到俩迭代器的“距离”,势必做了个iter++操作
template<typename _InputIterator>inline _GLIBCXX14_CONSTEXPRtypename iterator_traits<_InputIterator>::difference_type__distance(_InputIterator __first, _InputIterator __last,input_iterator_tag){// concept requirements__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)typename iterator_traits<_InputIterator>::difference_type __n = 0;while (__first != __last){++__first;++__n;}return __n;}
但是理论上你可以留个备份,然后给我恢复,不动我的输入才对。
这可能就和boost本身对迭代器的封装有关了。
也就是他distance的原理是让我的iter去++,最后去接近end,并且没给我备份恢复?
因为std::distance是模板操作,而迭代器是boost定义的,算是boost自己的问题,他不给副本,而走了智能指针,导致std::distance直接把iter给改掉了。
朴素的++iter操作,改变了boost的迭代器指向
结论就是避坑,单独给一个临时iter,或者别用stl接口去搞boost了。
或者问题根源在于:不要混用stl和boost
#include <boost/range.hpp>// ...std::vector<int> numbers{1, 2, 3, 4, 5};
auto range = boost::make_iterator_range(numbers);std::ptrdiff_t distance = boost::distance(range);
收回我刚才的话,不混用也没用,谨慎使用boost的迭代器,boost自己的distance函数一样改变了iter2的指向
如果有C++17,直接用C++的filesystem替代。
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <boost/filesystem.hpp>
#include <boost/range.hpp>
#include <boost/range/iterator_range.hpp>
// #include <filesystem>
#include <experimental/filesystem>
// namespace fs = boost::filesystem;
// namespace fs = std::filesystem;
int main() { std::experimental::filesystem::directory_iterator iter3("/home/hqw"), end3;std::cout <<"iter == iter_end? " << (iter3 == end3) <<std::endl;std::ptrdiff_t dist3 = std::distance(iter3, end3);std::cout <<"iter == iter_end? " << (iter3 == end3) <<std::endl;std::cout << "距离: " << dist3 << std::endl;return 0;
}