以下代码是在 OpenSUSE Tumbleweed 下编译的,带有 GCC 9.2.1 20190903修订版 275330
#include <vector>
#include <iostream>
int main()
{
std::vector<double> datos = {1, 2, 3, 4, 5, 6};
std::cout << "DEBUG: vector ";
for (auto d : datos)
std::cout << datos[d] << ' ';
std::cout << std::endl;
}
输出为
DEBUG: vector 2 3 4 5 6 0
但我期待
DEBUG: vector 1 2 3 4 5 6
然而,对于其他代码:
#include <vector>
#include <iostream>
int main()
{
std::vector<double> datos = {1, 1, 2, 3, 4, 5};
std::cout << "DEBUG: vector ";
for (auto d : datos)
std::cout << datos[d] << ' ';
std::cout << std::endl;
}
输出符合预期:
DEBUG: vector 1 1 2 3 4 5
命令行g++-9 test.cc
我错过了什么吗?这是编译器中的错误吗?
基于范围的 for 循环中变量 d 的值
for (auto d : datos)
std::cout << datos[d] << ' ';
不是向量中的索引。它是向量的当前元素的值
只需使用
for (auto d : datos)
std::cout << d << ' ';
对于这个载体
std::vector<double> datos = {1, 1, 2, 3, 4, 5};
你得到了预期的结果,因为
datos[datos[1]]
等于 1 即等于此元素
std::vector<double> datos = {1, 1, 2, 3, 4, 5};
^^^
datos[datos[1]]
再次产生相同的元素。
datos[datos[2]]
等于 2,依此类推。
例如,如果您将更改矢量,例如
std::vector<double> datos = { 5 };
然后,您将有未定义的行为,因为datos[datos[2]]
尝试访问超出为矢量元素分配的内存的内存。
无需深入细节,此循环
for (auto d : datos)
std::cout << d << ' ';
实际上相当于以下
for ( auto first = std::begin( datos ); first != std::end( datos ); ++first )
{
auto d = *first;
std::cout << d << ' ';
}
我错过了什么吗?
您将基于范围的循环与索引混合到矢量中 - 而是选择一种样式。修复了基于范围的 for 循环的示例(允许您直接迭代范围的元素(:
for (auto d : datos)
std::cout << d << ' ';
手动索引示例:
for (std::size_t i = 0; i < datos.size(); ++i)
std::cout << datos[i] << ' ';
对于基于范围的for
循环,该项已经是 int。
正确使用基于范围的for
循环
for (auto d : datos)
std::cout << d << ' ';
或使用传统循环
for (size_t d = 0; d < datos.size(); ++d)
std::cout << datos[d] << ' ';