1

我对 C++ 很陌生,我尝试过寻找答案并运行测试,但很多时候我都无法弄清楚导致特定行为的原因。我的问题与使用嵌套[ ]运算符访问或修改循环中的元素有关 - 例如:

//Declare

std::vector<int> a1 {10,20,30,40} ;
std::vector<int> a2 {2,3} ;
int S2 = a2.size() ; 

//Loop
for(int i = 0 ; i < S2 ; i++){
         a1[a2[i]] = a1[a2[i]] + 5000 ;
}

这被认为可以吗?我不仅在常规做法方面提出问题,而且在效率和我需要考虑的任何其他潜在因素方面也提出了问题。我是否应该首先存储a[i]在循环内的一个临时变量中,然后使用它来修改我在 vector 中的元素a2

我确实知道它可能不是最好的结构,我应该使用其他一些数据结构来做这种事情,但我只是想了解这是否可行,或者它是否可能导致一些未定义的行为。

4

4 回答 4

6

我是有限元计算软件的开发人员。

我们使用这种技术来访问元素内的值。它可以帮助我们节省大量内存

但是:请注意,它会破坏您的缓存位置。如果可以避免,请不要在繁重的循环中使用它。

如果你需要一个范围检查并且性能不重要,你可以考虑使用at操作符std::vector

 for(const auto & index :a2) {
      a1.at(index) += 5000;
 }

at函数自动检查 n 是否在向量中有效元素的范围内,如果不在则抛出 out_of_range 异常(即,如果 n 大于或等于其大小)。这与不检查边界的成员 operator[] 形成对比。

此外,考虑使用基于范围的循环

 //Loop
 for(const auto & index :a2) {
      a1[index] += 5000;
 }
于 2020-05-27T06:52:00.620 回答
5

这是完全正确的。

但实际上,您只是想迭代标准容器的元素。对于该用例, C++ 允许基于范围的 for 语句

for (index: a2) {
    a1[index] += 5000;
}

我发现它更具可读性,即使它主要是口味问题......

a2免责声明:此代码无法控制as index of的元素的有效性a1

于 2020-05-27T06:51:50.783 回答
2

在我看来没问题。无需创建a2[i].

我看到的唯一问题是里面的参数[]应该是 typestd::size_t而不是int. 这些整数类型包含不同范围的值,虽然std::size_t是无符号整数类型,但int也是有符号整数。注意使用负索引或超过最后一个元素的索引可能会由于越界访问而导致未定义的行为。但是,如果您可以保证 中的值a2始终是 的有效索引a1,那么这些int值将隐式转换为std::size_t并且事情正常(在您问题的代码示例中似乎就是这种情况)。

我还建议将循环变量转换i为(如果您想要完美std::size_t,请使用++i而不是:)。i++

在现代 C++ 中,您还可以使用基于范围的 for,因此您根本不需要使用显式索引变量来访问a2值:

for (auto indexFromA2 : a2)
    a1[indexFromA2] += 5000;

这不太容易出错,因为您必须编写更少的逻辑来管理元素访问(并且不必拼写类型)。

于 2020-05-27T06:43:45.773 回答
1

在尝试访问它们之前,我会以某种方式确保a1定义的元素a2确实存在,否则你会超出范围。

但就嵌套而言,[]这很好,无需创建另一个a2to access副本a1。编译器只是从内到外解开你的表达式。

你仍然可以稍微简化你的代码

 //Declare
 std::vector<int> a1 {10,20,30,40} ;
 std::vector<int> a2 {2,3} ;

 //Loop
 for(int i = 0 ; i < a2.size() ; i++){
          if(a1.size()-1 < a2[i]){break;}
          a1[a2[i]] += 5000 ;
 }
于 2020-05-27T06:37:38.273 回答