SKI*_*KIP 6 c++ unsigned for-loop
我有一个向量:
std::vector<int> vec = {1, 2, 3};
Run Code Online (Sandbox Code Playgroud)
我想做一个反向for循环。它有效,当我写:
for(int i = vec.size() - 1; i >= 0; --i) {
std::cout << i << std::endl; // 2, 1, 0
}
Run Code Online (Sandbox Code Playgroud)
但是如果我这样写,我会得到一个非常大的数字(比如 18446744073709223794):
for(size_t i = vec.size() - 1; i >= 0; --i) {
std::cout << i << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
但是当我写的时候它们都有效:
for(int i = 0; i < vec.size() - 1; ++i) {
std::cout << i << std::endl; // 1, 2, 3
}
// Or
for(size_t i = 0; i < vec.size() - 1; ++i) {
std::cout << i << std::endl; // 1, 2, 3
}
Run Code Online (Sandbox Code Playgroud)
为什么我在使用时得到了错误的向量大小size_t?
我认为转换有问题。
如果你在启用警告的情况下编译你的程序,编译器会告诉你这样的事情:
<source>: In function 'int main()':
7:43: warning: comparison of unsigned expression in '>= 0' is always true [-Wtype-limits]
7 | for(std::size_t i = vec.size() - 1; i >= 0; --i) {
| ~~^~~~
Run Code Online (Sandbox Code Playgroud)
这是为什么?这是因为std::size_t是C++ 中的无符号类型;它只代表非负数。阅读更多关于打开警告以及为什么它很重要:为什么我应该总是启用编译器警告?
我决定将我的答案拆分为一个单独的问题,与 OP 的错误无关。请去阅读它。
问题是它size_t是一个无符号整数,即它只能有正值。当您为无符号类型减少 0 时,会发生下溢,结果通常是该类型可表示的最大整数,例如 18446744073709223794 在您的情况下。最后,i >= 0对于任何无符号类型,检查始终为真,并且您的循环永远不会终止。