对 std::vector 使用嵌套 [ ] 操作
Using nested [ ] operations for std::vector
我是 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]
存储在循环内的临时变量中,然后使用它来修改向量 a2
中的元素?
我知道它可能不是最好的结构,我应该使用其他一些数据结构来做这种事情,但我只是想了解这是否可以,或者它是否会导致一些未定义的行为。
我会以某种方式确保在 a2
中定义的 a1
中的元素在尝试访问它们之前确实存在,否则你 运行 越界了。
但是对于嵌套 []
这很好,不需要创建另一个 a2
的副本来访问 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 ;
}
我觉得不错。无需创建 a2[i]
.
的显式副本
我看到的唯一问题是 []
中的参数类型应该是 std::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;
这不太容易出错,因为您必须编写更少的逻辑来管理元素访问(并且不必拼出类型)。
完全正确。
但实际上,你只是想迭代一个标准容器的元素。对于该用例,C++ 允许基于语句 的 范围:
for (index: a2) {
a1[index] += 5000;
}
我觉得它更具可读性,即使它主要是品味问题...
免责声明:此代码不控制 a2
的元素作为 a1
的索引的有效性。
我是一个有限元计算软件的开发者。
我们使用这种技术来访问元素内的值。它可以帮助我们节省大量内存
但是:请注意它会破坏您的缓存位置。如果可以避免,请不要在繁重的循环中使用它。
如果需要范围检查,性能不重要,可以考虑使用std::vector
的at
运算符
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;
}
我是 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]
存储在循环内的临时变量中,然后使用它来修改向量 a2
中的元素?
我知道它可能不是最好的结构,我应该使用其他一些数据结构来做这种事情,但我只是想了解这是否可以,或者它是否会导致一些未定义的行为。
我会以某种方式确保在 a2
中定义的 a1
中的元素在尝试访问它们之前确实存在,否则你 运行 越界了。
但是对于嵌套 []
这很好,不需要创建另一个 a2
的副本来访问 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 ;
}
我觉得不错。无需创建 a2[i]
.
我看到的唯一问题是 []
中的参数类型应该是 std::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;
这不太容易出错,因为您必须编写更少的逻辑来管理元素访问(并且不必拼出类型)。
完全正确。
但实际上,你只是想迭代一个标准容器的元素。对于该用例,C++ 允许基于语句 的 范围:
for (index: a2) {
a1[index] += 5000;
}
我觉得它更具可读性,即使它主要是品味问题...
免责声明:此代码不控制 a2
的元素作为 a1
的索引的有效性。
我是一个有限元计算软件的开发者。
我们使用这种技术来访问元素内的值。它可以帮助我们节省大量内存
但是:请注意它会破坏您的缓存位置。如果可以避免,请不要在繁重的循环中使用它。
如果需要范围检查,性能不重要,可以考虑使用std::vector
at
运算符
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;
}