【问题标题】:cant dereference out of range vector iterator- What's the problem?无法取消引用超出范围的向量迭代器 - 有什么问题?
【发布时间】:2019-09-13 17:55:33
【问题描述】:

我尝试使用向量来实现阶乘。结果假定附加vector<int> Res

 //corrected
 vector<int> Res;
 vector<int> Fact;

   for(int i=1; i!=4; i++)
        Fact.push_back(i);

int result=1;
  for (auto i = Fact.rbegin(), auto e= Fact.rend(); i != e; ++i)
      result *= *i; 

Res.push_back(result);

问题出在迭代器上。例外:不能取消引用超出范围的向量迭代器。 我不明白什么是迭代器超出范围? BegEnd 是在填写 Fact 后定义的。所以有什么问题?我只是初学者,我一定错过了这个主题的一些重要细节)

【问题讨论】:

  • 你们都减去 End 并从中减去 i。也许你的意思是*(End-1)
  • 不,我的意思是 *(End-i) 到达 for( ;End != Beg; End--) 的结尾。
  • 但你也可以End--。你在重复计算。而且*(End-i) 本身不会减少End,因此您的条件不需要达到true
  • 我认为你最好使用rbegin
  • @SergeyA 比较迭代器和反向迭代器需要多一步:stackoverflow.com/a/15203045/3365922

标签: c++ vector iterator


【解决方案1】:

End 是最后一个元素之后的迭代器,您不应该取消引用它(i 为 0 时,End-iEnd):

for (int i = 0; End != Beg; End--, i++)
      result *= *(End-i); 

我猜你需要这个:

for (; End != Beg; End--)
      result *= *(End-1); 

【讨论】:

  • @Konstantin 或者您可以使用反向迭代器(rbegin()rend())。是的,这行得通。但这不是应该接受的答案,因为它不是最好的解决方案。
【解决方案2】:

保留语义的最简单解决方案是使用reverse_iterator

for (auto i = Fact.rbegin(), e = Fact.rend(); i != e; ++i)
   result *= *i;

或者,使用accumulate:

result = std::accumulate(Fact.rbegin(), Fact.rend(), 0, [](int a, int b) { return a * b; })

或者,使用 C++20 和 ranges

for (int i : std::ranges::reverse_view{Fact}) 
    result *= i;

或者,由于乘法是可交换的,因此上述任何方法都具有前向迭代。

或者,因为任何数字乘以 0 都会产生 0,并且您从 0 开始:

result = 0;

【讨论】:

    【解决方案3】:
    1. end() 返回“最后一个元素之后的一个”。在你的第一关, i == 0,所以“最后一个减去零等于 kaboom”。

    2. 如果你碰巧知道你正在处理一个向量/连续内存,你可以someVec[length-n],只要你知道结果是一个有效的索引(n =大小都会不好)。对于这段代码,我根本不会使用迭代器。

    【讨论】:

    • 关于结束迭代器的错误。所有的双向迭代器都是可递减的,所有容器(包括地图和列表)都提供双向迭代器。
    • 我做了一些挖掘,你说的完全正确。我到底是从哪里得到这个主意的?也许是 15 年前的一些糟糕的 STL 实现。呵呵。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-27
    • 1970-01-01
    相关资源
    最近更新 更多