我正在编写一个代码,它使用迭代器上的简单算法将向量分成相等的部分。我的逻辑可能不是很好(虽然我很确定这是正确的)这可能意味着我创建了一个无效的迭代器,结束了end():
//selectWords is a vector<string>
//No is an unsigned integer.
unsigned wordNo = selectWords.size()/No;
unsigned remainder = selectWords.size()%No;
for(auto i = 0; i < No; ++i){
unsigned extra = remainder ? 1 : 0;
auto b = selectedWords.begin()+(i*wordNo);
auto e = selectedWords.begin() + ((i+1)*wordNo) + extra;
if(e > selectedWords.end()) throw logic_error("Iterator e in GridList::createGrids goes past the end of selectWords.") //shouldn't happen unless I've made a mistake.
...
//do stuff
...
if(remainder > 0) --remainder;
}
我很好奇的部分是e > selectedWords.end()
。如果e
已经过end()
,那么它是一个无效的迭代器,我不确定是否有任何保证比较运算符提供已定义的行为。确实在this thread和N3337的24.2.7中查看Ben Voigt的帖子很明显,使用迭代器算法创建一个past-the-end()迭代器是没有意义的或非法的。然而,检查迭代器是否超过end()的能力要求对past-the-end()迭代器的操作提供定义的行为。
如果进行此比较无效,还有其他方法吗?或者我必须在编译之前确保我的逻辑是正确的吗?
答案 0 :(得分:0)
经过一个结束迭代器(例如递增它)会给出未定义的行为。
如果某些内容只能由于未定义的行为而存在,则由于在具有明确定义的行为的代码中执行任何操作,它不会存在。从逻辑上讲,这意味着不需要为其定义测试方式。
答案 1 :(得分:0)
您只需更正代码即可获得正确的结束位置:
size_t No = 3;
std::vector<int> selectWords = {1,2,3,4,5,6,7,8,9,10};
size_t wordNo = (selectWords.size() + No - 1)/No;
size_t remainder = selectWords.size()%No;
for(size_t i = 0; i < No; ++i){
size_t start_index = i * wordNo;
size_t end_index = std::min(selectWords.size(), start_index + wordNo);
auto b = selectWords.begin() + start_index;
auto e = selectWords.begin() + end_index;
for (auto it = b; it != e; ++it)
std::cout << *it;
//....
}