在嵌套 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分配了一个寄存器。所以,使用的内存是一样的。