在嵌套 for 循环内部和外部声明整数迭代器之间使用的内存差异
Difference in memory used between declaring integer iterator inside and outside a nested for-loop
代码 1:
int solution(vector<vector<int>>& arr){
int ans, m = arr.size(), n = arr[0].size(); // it is given that m is atleast 1
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
// do something
// i and j are only used for iterating over the array
}
}
return ans;
}
代码 2:
int solution(vector<vector<int>>& arr){
int i, j, ans, m = arr.size(), n = arr[0].size();
for(i = 0; i < m; i++){
for(j = 0; j < n; j++){
// do something
}
}
return ans;
}
我认为 code2 使用更少的内存,因为 code1 在 for 循环中声明了变量 j
m
次(正如评论和答案中提到的那样,这不是真的)。但是当我在在线编码平台上看到许多编码器更喜欢使用 code1 而不是 code2 时,我感到怀疑。
我很感激任何关于这两个代码使用的内存差异的解释。
正如 Andreas Brunnet
所建议的那样,我尝试编译 godbolt.org
中的两个代码,并且 HolyBlackCat
表示这两个代码的汇编代码是相同的。下面是使用的代码和对应的汇编代码(编译选项为x86-64 gcc 11.2
)。
代码:
#include <vector>
int sum(std::vector<std::vector<int>> arr) {
int i, j, ans = 0, m = arr.size(), n = arr[0].size(); // i, j deleted in code2
for(i = 0; i < m; i++){ // int i = 0 in code2
for(j = 0; j < n; j++){ // int j = 0 in code2
ans += arr[i][j];
}
}
return ans;
}
两个代码的汇编代码是:
sum(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >):
push rbp
mov rbp, rsp
sub rsp, 48
mov QWORD PTR [rbp-40], rdi
mov DWORD PTR [rbp-12], 0
mov rax, QWORD PTR [rbp-40]
mov rdi, rax
call std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >::size() const
mov DWORD PTR [rbp-16], eax
mov rax, QWORD PTR [rbp-40]
mov esi, 0
mov rdi, rax
call std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >::operator[](unsigned long)
mov rdi, rax
call std::vector<int, std::allocator<int> >::size() const
mov DWORD PTR [rbp-20], eax
mov DWORD PTR [rbp-4], 0
jmp .L2
.L5:
mov DWORD PTR [rbp-8], 0
jmp .L3
.L4:
mov eax, DWORD PTR [rbp-4]
movsx rdx, eax
mov rax, QWORD PTR [rbp-40]
mov rsi, rdx
mov rdi, rax
call std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >::operator[](unsigned long)
mov rdx, rax
mov eax, DWORD PTR [rbp-8]
cdqe
mov rsi, rax
mov rdi, rdx
call std::vector<int, std::allocator<int> >::operator[](unsigned long)
mov eax, DWORD PTR [rax]
add DWORD PTR [rbp-12], eax
add DWORD PTR [rbp-8], 1
.L3:
mov eax, DWORD PTR [rbp-8]
cmp eax, DWORD PTR [rbp-20]
jl .L4
add DWORD PTR [rbp-4], 1
.L2:
mov eax, DWORD PTR [rbp-4]
cmp eax, DWORD PTR [rbp-16]
jl .L5
mov eax, DWORD PTR [rbp-12]
leave
ret
据我了解,汇编代码中的第18、19、43、45、46、47行对应于c++代码的第5行,第21、22、38、40、41、42行对应于第6行(如果我错了请纠正我)。即
18: mov DWORD PTR [rbp-4], 0
19: jmp .L2
43: add DWORD PTR [rbp-4], 1
44:.L2:
45: mov eax, DWORD PTR [rbp-4]
46: cmp eax, DWORD PTR [rbp-16]
47: jl .L5
是for((int) i = 0; i < m; i++)
和
对应的代码
20:.L5:
21: mov DWORD PTR [rbp-8], 0
22: jmp .L3
38: add DWORD PTR [rbp-8], 1
39:.L3:
40: mov eax, DWORD PTR [rbp-8]
41: cmp eax, DWORD PTR [rbp-20]
42: jl .L4
对应for((int) j = 0; j < n; j++)
很明显,编译器在两个代码中都只为j
分配了一个寄存器。所以,使用的内存是一样的。
代码 1:
int solution(vector<vector<int>>& arr){
int ans, m = arr.size(), n = arr[0].size(); // it is given that m is atleast 1
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
// do something
// i and j are only used for iterating over the array
}
}
return ans;
}
代码 2:
int solution(vector<vector<int>>& arr){
int i, j, ans, m = arr.size(), n = arr[0].size();
for(i = 0; i < m; i++){
for(j = 0; j < n; j++){
// do something
}
}
return ans;
}
我认为 code2 使用更少的内存,因为 code1 在 for 循环中声明了变量 j
m
次(正如评论和答案中提到的那样,这不是真的)。但是当我在在线编码平台上看到许多编码器更喜欢使用 code1 而不是 code2 时,我感到怀疑。
我很感激任何关于这两个代码使用的内存差异的解释。
正如 Andreas Brunnet
所建议的那样,我尝试编译 godbolt.org
中的两个代码,并且 HolyBlackCat
表示这两个代码的汇编代码是相同的。下面是使用的代码和对应的汇编代码(编译选项为x86-64 gcc 11.2
)。
代码:
#include <vector>
int sum(std::vector<std::vector<int>> arr) {
int i, j, ans = 0, m = arr.size(), n = arr[0].size(); // i, j deleted in code2
for(i = 0; i < m; i++){ // int i = 0 in code2
for(j = 0; j < n; j++){ // int j = 0 in code2
ans += arr[i][j];
}
}
return ans;
}
两个代码的汇编代码是:
sum(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >):
push rbp
mov rbp, rsp
sub rsp, 48
mov QWORD PTR [rbp-40], rdi
mov DWORD PTR [rbp-12], 0
mov rax, QWORD PTR [rbp-40]
mov rdi, rax
call std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >::size() const
mov DWORD PTR [rbp-16], eax
mov rax, QWORD PTR [rbp-40]
mov esi, 0
mov rdi, rax
call std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >::operator[](unsigned long)
mov rdi, rax
call std::vector<int, std::allocator<int> >::size() const
mov DWORD PTR [rbp-20], eax
mov DWORD PTR [rbp-4], 0
jmp .L2
.L5:
mov DWORD PTR [rbp-8], 0
jmp .L3
.L4:
mov eax, DWORD PTR [rbp-4]
movsx rdx, eax
mov rax, QWORD PTR [rbp-40]
mov rsi, rdx
mov rdi, rax
call std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >::operator[](unsigned long)
mov rdx, rax
mov eax, DWORD PTR [rbp-8]
cdqe
mov rsi, rax
mov rdi, rdx
call std::vector<int, std::allocator<int> >::operator[](unsigned long)
mov eax, DWORD PTR [rax]
add DWORD PTR [rbp-12], eax
add DWORD PTR [rbp-8], 1
.L3:
mov eax, DWORD PTR [rbp-8]
cmp eax, DWORD PTR [rbp-20]
jl .L4
add DWORD PTR [rbp-4], 1
.L2:
mov eax, DWORD PTR [rbp-4]
cmp eax, DWORD PTR [rbp-16]
jl .L5
mov eax, DWORD PTR [rbp-12]
leave
ret
据我了解,汇编代码中的第18、19、43、45、46、47行对应于c++代码的第5行,第21、22、38、40、41、42行对应于第6行(如果我错了请纠正我)。即
18: mov DWORD PTR [rbp-4], 0
19: jmp .L2
43: add DWORD PTR [rbp-4], 1
44:.L2:
45: mov eax, DWORD PTR [rbp-4]
46: cmp eax, DWORD PTR [rbp-16]
47: jl .L5
是for((int) i = 0; i < m; i++)
和
20:.L5:
21: mov DWORD PTR [rbp-8], 0
22: jmp .L3
38: add DWORD PTR [rbp-8], 1
39:.L3:
40: mov eax, DWORD PTR [rbp-8]
41: cmp eax, DWORD PTR [rbp-20]
42: jl .L4
对应for((int) j = 0; j < n; j++)
很明显,编译器在两个代码中都只为j
分配了一个寄存器。所以,使用的内存是一样的。