从逆序 C++ 访问向量时出现运行时错误 [关闭]

Posted

技术标签:

【中文标题】从逆序 C++ 访问向量时出现运行时错误 [关闭]【英文标题】:Runtime error in accessing vector from reverse order C++ [closed] 【发布时间】:2020-01-09 19:42:31 【问题描述】:

我试图以相反的顺序访问存储在向量中的值。以下代码显示没有错误:

for (long long int i = 0; i < end.size(); i++)
    cout << end[end.size() - 1 - i] << "\n";

但以下代码显示运行时错误:

for(long long int i = end.size()-1;i>=0;i--) cout<<end[i]<<"\n";

这两种方法有区别吗?

【问题讨论】:

不相关,但 C++ 中的容器有 rbeginrend(反向迭代器)。 我无法重现您的错误。你能准备一个minimal complete example吗? 这两种方法有什么区别吗? -- 在空向量上尝试第二种方法。 不要把你的向量称为end,这只会让事情变得混乱。 【参考方案1】:

这两种方法有区别吗?

end.size() 返回std::size_t,这是一个无符号类型。给定一个空向量,从无符号零中减去 1。由于无符号数使用模运算,结果是一个非常大的无符号数。

在这里,行为取决于语言的版本以及实现。如果long long 可以表示大的无符号值,那么您将使用这个大索引(任何索引超出空向量的范围)溢出数组,并且行为将是未定义的。这将发生在 32 位系统上,其中std::size_t 大概是 32 位和 long long 64 位。

如果 long long 无法表示该值,则在 C++20 之前,结果值将由实现定义。如果该值为负数,那么您有所需的行为,其他明智的未定义行为。在 C++20 之后,结果将与可表示值以可表示值的数量为模一致。如果long long 的位宽与std::size_t 匹配,则结果将为-1,并且行为将符合预期。

结论:后一种方法在某些实现上被破坏了。第一个没有这个问题。

【讨论】:

为什么是“理论上”?它只是坏了,不是吗? @foreknownas_463035818 在具有 2 的补码表示和 long longstd::size_t 大小相同的系统上,它可以在实践中工作。这样的系统相当普遍。问题本质上在于与该描述不匹配的系统的可移植性。 @foreknownas_463035818 我从“理论上”删除了,因为我发现问题存在于所有 32 位或更小的系统上。【参考方案2】:

正确的做法是:

for(auto i=end.size(); i-- ;) cout << end[i] << "\n" ;

【讨论】:

不是,不是。正确的方法是使用反向迭代器。无论如何,您没有回答问题 那不是“正确”的推荐版本;它甚至不等价(它不打印第一个值)。

以上是关于从逆序 C++ 访问向量时出现运行时错误 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

添加向量时出现分段错误。 (C++)

在 C++ 中比较来自向量的字符串时出现分段错误

在 C++ 索引程序中使用向量时出现分段错误 11

从成员函数打印 vector<int> 元素时出现 C++ 段错误

在 C++ 中使用向量时出现分段错误

C++ vector 和 Gtkmm 能完美地协同工作吗?从 gtkmm on_click 方法获取向量<string> 的值时出现分段错误