函数简单传入参数的汇编分析

文章目录

1.演示代码

cpp 复制代码
#include <iostream>

// 无参数函数
void funcNoParams() {
    std::cout << "无参数函数被调用" << std::endl;
}

// 单个参数函数
void funcOneParam(int a) {
    std::cout << "单参数函数: " << a << std::endl;
}

// 两个参数函数
void funcTwoParams(int a, int b) {
    std::cout << "双参数函数: " << a << ", " << b << std::endl;
}

// 三个参数函数
void funcThreeParams(int a, int b, int c) {
    std::cout << "三参数函数: " << a << ", " << b << ", " << c << std::endl;
}

// 多个参数函数(15个参数)
void funcManyParams(int a1, int a2, int a3, int a4, int a5,
    int a6, int a7, int a8, int a9, int a10,
    int a11, int a12, int a13, int a14, int a15) {
    std::cout << "15参数函数调用:" << std::endl;
    std::cout << "前5个参数: " << a1 << ", " << a2 << ", " << a3 << ", " << a4 << ", " << a5 << std::endl;
    std::cout << "中5个参数: " << a6 << ", " << a7 << ", " << a8 << ", " << a9 << ", " << a10 << std::endl;
    std::cout << "后5个参数: " << a11 << ", " << a12 << ", " << a13 << ", " << a14 << ", " << a15 << std::endl;
}
 

int main() {
    //std::cout << "=== 函数参数传递对比演示 ===" << std::endl;

    // 演示无参数函数调用
    //std::cout << "\n--- 无参数函数调用 ---" << std::endl;
    funcNoParams();

    // 演示单个参数函数调用
    //std::cout << "\n--- 单参数函数调用 ---" << std::endl;
    int x = 10;
    funcOneParam(x);           // 使用变量
    funcOneParam(20);          // 使用字面量
    funcOneParam(x + 5);       // 使用表达式

    // 演示两个参数函数调用
    //std::cout << "\n--- 双参数函数调用 ---" << std::endl;
    int y = 30;
    funcTwoParams(x, y);       // 使用两个变量
    funcTwoParams(40, 50);     // 使用两个字面量
    funcTwoParams(x, y * 2);   // 混合使用变量和表达式

    // 演示三个参数函数调用
    //std::cout << "\n--- 三参数函数调用 ---" << std::endl;
    int z = 60;
    funcThreeParams(x, y, z);  // 使用三个变量
    funcThreeParams(70, 80, 90); // 使用三个字面量

    // 演示多个参数函数调用(使用变量)
    //std::cout << "\n--- 多参数函数调用(使用变量)---" << std::endl;
    int var1 = 100, var2 = 200, var3 = 300, var4 = 400, var5 = 500;
    int var6 = 600, var7 = 700, var8 = 800, var9 = 900, var10 = 1000;
    int var11 = 1100, var12 = 1200, var13 = 1300, var14 = 1400, var15 = 1500;

    funcManyParams(var1, var2, var3, var4, var5,
        var6, var7, var8, var9, var10,
        var11, var12, var13, var14, var15);
    return 0;
}

2.演示代码对应的汇编代码

3.主函数调用部分

cpp 复制代码
int main() {
00412444  in          al,dx  
00412445  cwde  
00412446  add         dword ptr [eax],eax  
00412448  add         byte ptr [ebx+56h],dl  
0041244B  push        edi  
0041244C  lea         edi,[ebp-0D8h]  
00412452  mov         ecx,36h  
00412457  mov         eax,0CCCCCCCCh  
0041245C  rep stos    dword ptr es:[edi]  
0041245E  mov         ecx,offset _C66D3399_simple_cpp@cpp (0420077h)  
00412463  call        @__CheckForDebuggerJustMyCode@4 (04113C5h)  
00412468  nop  
    //std::cout << "=== 函数参数传递对比演示 ===" << std::endl;

    // 演示无参数函数调用
    //std::cout << "\n--- 无参数函数调用 ---" << std::endl;
    funcNoParams();
00412469  call        funcNoParams (0411532h)  
0041246E  nop  

    // 演示单个参数函数调用
    //std::cout << "\n--- 单参数函数调用 ---" << std::endl;
    int x = 10;
0041246F  mov         dword ptr [x],0Ah  
    funcOneParam(x);           // 使用变量
00412476  mov         eax,dword ptr [x]  
00412479  push        eax  
0041247A  call        funcOneParam (041152Dh)  
0041247F  add         esp,4  
    funcOneParam(20);          // 使用字面量
00412482  push        14h  
00412484  call        funcOneParam (041152Dh)  
00412489  add         esp,4  
    funcOneParam(x + 5);       // 使用表达式
0041248C  mov         eax,dword ptr [x]  
0041248F  add         eax,5  
00412492  push        eax  
00412493  call        funcOneParam (041152Dh)  
00412498  add         esp,4  

    // 演示两个参数函数调用
    //std::cout << "\n--- 双参数函数调用 ---" << std::endl;
    int y = 30;
0041249B  mov         dword ptr [y],1Eh  
    funcTwoParams(x, y);       // 使用两个变量
004124A2  mov         eax,dword ptr [y]  
004124A5  push        eax  
004124A6  mov         ecx,dword ptr [x]  
004124A9  push        ecx  
004124AA  call        funcTwoParams (0411528h)  
004124AF  add         esp,8  
    funcTwoParams(40, 50);     // 使用两个字面量
004124B2  push        32h  
004124B4  push        28h  
004124B6  call        funcTwoParams (0411528h)  
004124BB  add         esp,8  
    funcTwoParams(x, y * 2);   // 混合使用变量和表达式
004124BE  mov         eax,dword ptr [y]  
004124C1  shl         eax,1  
004124C3  push        eax  
004124C4  mov         ecx,dword ptr [x]  
004124C7  push        ecx  
004124C8  call        funcTwoParams (0411528h)  
004124CD  add         esp,8  

    // 演示三个参数函数调用
    //std::cout << "\n--- 三参数函数调用 ---" << std::endl;
    int z = 60;
004124D0  mov         dword ptr [z],3Ch  
    funcThreeParams(x, y, z);  // 使用三个变量
004124D7  mov         eax,dword ptr [z]  
004124DA  push        eax  
004124DB  mov         ecx,dword ptr [y]  
004124DE  push        ecx  
004124DF  mov         edx,dword ptr [x]  
004124E2  push        edx  
004124E3  call        funcThreeParams (041153Ch)  
004124E8  add         esp,0Ch  
    funcThreeParams(70, 80, 90); // 使用三个字面量
004124EB  push        5Ah  
004124ED  push        50h  
004124EF  push        46h  
004124F1  call        funcThreeParams (041153Ch)  
004124F6  add         esp,0Ch  

    // 演示多个参数函数调用(使用变量)
    //std::cout << "\n--- 多参数函数调用(使用变量)---" << std::endl;
    int var1 = 100, var2 = 200, var3 = 300, var4 = 400, var5 = 500;
004124F9  mov         dword ptr [var1],64h  
00412500  mov         dword ptr [var2],0C8h  
00412507  mov         dword ptr [var3],12Ch  
0041250E  mov         dword ptr [var4],190h  
00412515  mov         dword ptr [var5],1F4h  
    int var6 = 600, var7 = 700, var8 = 800, var9 = 900, var10 = 1000;
0041251C  mov         dword ptr [var6],258h  
00412523  mov         dword ptr [var7],2BCh  
0041252A  mov         dword ptr [var8],320h  
00412531  mov         dword ptr [var9],384h  
0041253B  mov         dword ptr [var10],3E8h  
    int var11 = 1100, var12 = 1200, var13 = 1300, var14 = 1400, var15 = 1500;
00412545  mov         dword ptr [var11],44Ch  
0041254F  mov         dword ptr [var12],4B0h  
00412559  mov         dword ptr [var13],514h  
00412563  mov         dword ptr [var14],578h  
0041256D  mov         dword ptr [var15],5DCh  

    funcManyParams(var1, var2, var3, var4, var5,
00412577  mov         eax,dword ptr [var15]  
0041257D  push        eax  
0041257E  mov         ecx,dword ptr [var14]  
00412584  push        ecx  
00412585  mov         edx,dword ptr [var13]  
0041258B  push        edx  
0041258C  mov         eax,dword ptr [var12]  
00412592  push        eax  
00412593  mov         ecx,dword ptr [var11]  
00412599  push        ecx  
0041259A  mov         edx,dword ptr [var10]  
004125A0  push        edx  
004125A1  mov         eax,dword ptr [var9]  
004125A7  push        eax  
004125A8  mov         ecx,dword ptr [var8]  
004125AB  push        ecx  
004125AC  mov         edx,dword ptr [var7]  
004125AF  push        edx  
004125B0  mov         eax,dword ptr [var6]  
004125B3  push        eax  
004125B4  mov         ecx,dword ptr [var5]  
004125B7  push        ecx  
004125B8  mov         edx,dword ptr [var4]  
004125BB  push        edx  
004125BC  mov         eax,dword ptr [var3]  
004125BF  push        eax  
004125C0  mov         ecx,dword ptr [var2]  
004125C3  push        ecx  
004125C4  mov         edx,dword ptr [var1]  
004125C7  push        edx  
004125C8  call        funcManyParams (0411537h)  
004125CD  add         esp,3Ch  
        var6, var7, var8, var9, var10,
        var11, var12, var13, var14, var15);
    return 0;
004125D0  xor         eax,eax  
}
004125D2  pop         edi  
004125D3  pop         esi  
004125D4  pop         ebx  
004125D5  add         esp,198h  
004125DB  cmp         ebp,esp  
004125DD  call        __RTC_CheckEsp (04112C1h)  
004125E2  mov         esp,ebp  
004125E4  pop         ebp  
004125E5  ret  

您说得对,我的分析确实不够完整。让我提供更全面的分析,包括函数调用前后的完整栈帧管理和所有细节:

完整的主函数栈帧建立

cpp 复制代码
int main() {
00412444  in          al,dx  
00412445  cwde  
00412446  add         dword ptr [eax],eax  
00412448  add         byte ptr [ebx+56h],dl  
0041244B  push        edi  
0041244C  lea         edi,[ebp-0D8h]  
00412452  mov         ecx,36h  
00412457  mov         eax,0CCCCCCCCh  
0041245C  rep stos    dword ptr es:[edi]  
0041245E  mov         ecx,offset _C66D3399_simple_cpp@cpp (0420077h)  
00412463  call        @__CheckForDebuggerJustMyCode@4 (04113C5h)  
00412468  nop  

详细分析

  • push edi - 保存EDI寄存器
  • lea edi,[ebp-0D8h] - 计算局部变量区域的起始地址
  • mov ecx,36h - 设置循环次数(54次)
  • mov eax,0CCCCCCCCh - 调试模式的填充值(未初始化内存)
  • rep stos - 用0xCC填充局部变量空间(调试特征)
  • 调用调试检查函数

1. 无参数函数调用(完整分析)

cpp 复制代码
funcNoParams();
00412469  call        funcNoParams (0411532h)  
0041246E  nop  

完整调用过程

  • call 指令:将返回地址(0041246E)压栈,跳转到函数
  • 函数执行完毕后返回到 nop 指令
  • 无参数,无栈调整

2. 单参数函数调用(三种场景对比)

场景1:变量传递

cpp 复制代码
int x = 10;
0041246F  mov         dword ptr [x],0Ah  
funcOneParam(x);
00412476  mov         eax,dword ptr [x]  ; 从内存加载x到eax
00412479  push        eax               ; 参数压栈
0041247A  call        funcOneParam (041152Dh)  
0041247F  add         esp,4             ; 调用者清理栈(1参数=4字节)

场景2:字面量传递

cpp 复制代码
funcOneParam(20);
00412482  push        14h               ; 直接压入字面量20(0x14)
00412484  call        funcOneParam (041152Dh)  
00412489  add         esp,4  

场景3:表达式传递

cpp 复制代码
funcOneParam(x + 5);
0041248C  mov         eax,dword ptr [x]  ; 加载x
0041248F  add         eax,5             ; 计算表达式(x+5)
00412492  push        eax               ; 结果压栈
00412493  call        funcOneParam (041152Dh)  
00412498  add         esp,4  

3. 双参数函数调用(完整分析)

cpp 复制代码
int y = 30;
0041249B  mov         dword ptr [y],1Eh  

funcTwoParams(x, y);
004124A2  mov         eax,dword ptr [y]  ; 加载第二个参数y
004124A5  push        eax               ; 先压入y(从右向左)
004124A6  mov         ecx,dword ptr [x]  ; 加载第一个参数x
004124A9  push        ecx               ; 后压入x
004124AA  call        funcTwoParams (0411528h)  
004124AF  add         esp,8             ; 清理8字节(2参数)

4. 三参数函数调用(寄存器使用分析)

cpp 复制代码
int z = 60;
004124D0  mov         dword ptr [z],3Ch  

funcThreeParams(x, y, z);
004124D7  mov         eax,dword ptr [z]  ; 使用eax加载第三个参数
004124DA  push        eax               ; 压入z
004124DB  mov         ecx,dword ptr [y]  ; 使用ecx加载第二个参数
004124DE  push        ecx               ; 压入y
004124DF  mov         edx,dword ptr [x]  ; 使用edx加载第一个参数
004124E2  push        edx               ; 压入x
004124E3  call        funcThreeParams (041153Ch)  
004124E8  add         esp,0Ch           ; 清理12字节(3参数)

5. 15参数函数调用(完整栈操作)

cpp 复制代码
funcManyParams(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15);
00412577  mov         eax,dword ptr [var15]  ; 第15个参数
0041257D  push        eax
0041257E  mov         ecx,dword ptr [var14]  ; 第14个参数  
00412584  push        ecx
; ... 中间13个参数的push操作 ...
004125C4  mov         edx,dword ptr [var1]   ; 第1个参数
004125C7  push        edx
004125C8  call        funcManyParams (0411537h)  
004125CD  add         esp,3Ch           ; 清理60字节(15×4字节)

6. 函数返回和栈帧销毁

assembly 复制代码
return 0;
004125D0  xor         eax,eax           ; 返回值0
}
004125D2  pop         edi               ; 恢复EDI
004125D3  pop         esi               ; 恢复ESI  
004125D4  pop         ebx               ; 恢复EBX
004125D5  add         esp,198h          ; 调整栈指针,释放局部变量空间
004125DB  cmp         ebp,esp           ; 检查栈平衡
004125DD  call        __RTC_CheckEsp (04112C1h)  ; 运行时栈检查
004125E2  mov         esp,ebp           ; 恢复栈指针
004125E4  pop         ebp               ; 恢复基址指针
004125E5  ret                          ; 返回

关键技术细节总结:

1. 调用约定特征

  • cdecl调用约定:参数从右向左压栈,调用者清理栈
  • 栈清理方式add esp, N(N=参数个数×4)

2. 寄存器使用模式

  • 参数传递:全部使用栈,未使用寄存器传参
  • 临时存储:eax, ecx, edx 用于加载参数值
  • 保存寄存器:ebx, esi, edi 在函数开始时保存

3. 内存布局

c 复制代码
栈顶 → [参数n] ... [参数2] [参数1] [返回地址] [保存的ebp] [局部变量]

4. 调试特征

  • 0xCCCCCCCC 填充:未初始化内存的调试标记
  • __CheckForDebuggerJustMyCode:调试器检查
  • __RTC_CheckEsp:运行时栈检查

5. 性能优化点

  • 字面量直接压栈,避免内存加载
  • 表达式在压栈前计算完成
  • 寄存器重用优化(不同参数使用不同寄存器)

这个完整的分析展示了x86架构下C++函数调用的完整机制,包括参数传递、栈管理和调试支持的所有细节。

传递参数和不传递参数有啥区别,如果从堆栈的角度传递参数和不传递参数有什么区别

从堆栈角度分析,传递参数和不传递参数有本质区别。让我详细对比:

1. 无参数函数调用的堆栈变化

c 复制代码
funcNoParams();
00412469  call        funcNoParams (0411532h)  
0041246E  nop  

堆栈变化

c 复制代码
调用前堆栈: [返回地址] [保存的ebp] [局部变量] ...
↓ call指令执行
调用中堆栈: [新的返回地址(0041246E)] [旧的返回地址] [保存的ebp] [局部变量] ...
              ↑
              栈顶下移4字节,只压入返回地址

2. 有参数函数调用的堆栈变化

单参数例子:

c 复制代码
funcOneParam(x);
00412476  mov eax,dword ptr [x]  
00412479  push eax              ; 参数压栈
0041247A  call funcOneParam     ; 返回地址压栈
0041247F  add esp,4             ; 清理参数

堆栈变化

c 复制代码
调用前堆栈: [返回地址] [保存的ebp] [局部变量] ...
↓ push eax
           [参数x] [返回地址] [保存的ebp] [局部变量] ...
↓ call指令执行  
           [新的返回地址] [参数x] [旧的返回地址] [保存的ebp] [局部变量] ...
              ↑
              栈顶下移8字节(参数4+返回地址4)

3. 关键区别对比

方面 无参数调用 有参数调用
栈空间占用 只压入返回地址(4字节) 返回地址+所有参数大小
栈指针调整 call前后esp-4 push参数时esp-N,call时esp-4,清理时esp+N
内存访问 无额外内存访问 需要访问参数所在内存位置
执行时间 较短 较长(与参数数量成正比)
堆栈布局 简单 复杂,需要维护参数区

4. 具体堆栈布局对比

无参数调用时的堆栈帧:

c 复制代码
高地址 → [调用者的栈帧]
         [main函数的返回地址]
         [保存的ebp]        ← ebp指向这里
         [局部变量x,y,z...] ← esp指向这里
低地址 → [空栈空间]

调用funcNoParams时:

c 复制代码
高地址 → [调用者的栈帧]
         [main函数的返回地址]
         [保存的ebp]        
         [局部变量x,y,z...] 
         [funcNoParams返回地址(0041246E)] ← esp指向这里
低地址 → [空栈空间]

有参数调用时的堆栈帧(以funcTwoParams为例):

调用前:

c 复制代码
高地址 → [调用者的栈帧]
         [main函数的返回地址]
         [保存的ebp]        
         [局部变量x,y,z...] ← esp指向这里
低地址 → [空栈空间]

调用过程中:

c 复制代码
高地址 → [调用者的栈帧]
         [main函数的返回地址]
         [保存的ebp]        
         [局部变量x,y,z...] 
         [参数y]           ← push eax (y)
         [参数x]           ← push ecx (x)  
         [返回地址]         ← call指令,esp指向这里
低地址 → [空栈空间]

5. 从函数内部视角看区别

无参数函数内部访问:

cpp 复制代码
void funcNoParams() {
    // 只能访问自己的局部变量
    // 无法通过参数访问调用者的数据
}

有参数函数内部访问:

cpp 复制代码
void funcTwoParams(int a, int b) {
    // 可以通过ebp+8访问第一个参数a
    // 可以通过ebp+12访问第二个参数b  
    // 汇编中通常:a=[ebp+8], b=[ebp+12]
}

函数内部的堆栈视角

c 复制代码
高地址 → [调用者的栈帧]
         [返回地址]         ← ebp+4
         [保存的ebp]        ← ebp指向这里
         [局部变量]         ← ebp-4, ebp-8, ...
         [参数1]           ← ebp+8  (第一个参数)
         [参数2]           ← ebp+12 (第二个参数)
         [参数...]         ← ebp+16, ...
低地址 → [空栈空间]         ← esp指向这里

6. 性能影响分析

无参数调用:

  • 栈操作:1次call(隐含1次push)
  • 内存访问:无额外内存访问
  • 指令数:1条call指令

有参数调用(N个参数):

  • 栈操作:N次push + 1次call(隐含1次push)+ 1次add esp
  • 内存访问:N次参数加载 + N次push写入
  • 指令数:约3N+2条指令

7. 实际堆栈示例对比

场景1:无参数调用

c 复制代码
调用前: ESP = 0x0018FF34
调用中: ESP = 0x0018FF30  (压入返回地址)
堆栈内容: [0x0018FF30: 0041246E] ← 返回地址

场景2:双参数调用

c 复制代码
调用前: ESP = 0x0018FF34
push y:  ESP = 0x0018FF30, [0x0018FF30: 30] ← 参数y
push x:  ESP = 0x0018FF2C, [0x0018FF2C: 10] ← 参数x  
call:    ESP = 0x0018FF28, [0x0018FF28: 004124AF] ← 返回地址
清理后:  ESP = 0x0018FF34  (恢复原状)

总结

从堆栈角度看,传递参数的本质是在调用函数前,在栈上为被调用函数准备数据空间。这种区别导致:

  1. 栈空间占用:有参数调用需要更多栈空间
  2. 执行开销:有参数调用有额外的push/pop操作
  3. 内存访问:有参数调用需要访问参数内存位置
  4. 代码复杂度:有参数调用需要维护参数传递协议

这就是为什么在性能敏感的场景中,应该尽量减少参数数量,或者使用寄存器传递参数(如x64架构的fastcall约定)。

4. 函数内部是如何使用这些传入的参数的呢

从你提供的汇编代码可以看出,在x86架构下使用__cdecl调用约定时,函数内部访问参数的方式。让我详细分析每种场景:

1. 单个参数函数 funcOneParam(int a)

参数访问方式:

c 复制代码
mov eax, dword ptr [a]        ; 从栈中读取参数a的值到eax寄存器
mov dword ptr [result], eax   ; 将eax的值存入局部变量result

栈帧结构:

c 复制代码
[ebp+8]  - 参数a
[ebp+4]  - 返回地址
[ebp]    - 保存的ebp
[ebp-4]  - 局部变量result

2. 两个参数函数 funcTwoParams(int a, int b)

参数访问方式:

c 复制代码
mov eax, dword ptr [a]        ; 读取第一个参数a
add eax, dword ptr [b]        ; 加上第二个参数b
mov dword ptr [result], eax   ; 存储结果

栈帧结构:

c 复制代码
[ebp+12] - 参数b
[ebp+8]  - 参数a  
[ebp+4]  - 返回地址
[ebp]    - 保存的ebp
[ebp-4]  - 局部变量result

3. 三个参数函数 funcThreeParams(int a, int b, int c)

参数访问方式:

c 复制代码
mov eax, dword ptr [a]        ; 读取参数a
add eax, dword ptr [b]        ; 加上参数b
add eax, dword ptr [c]        ; 加上参数c
mov dword ptr [result], eax   ; 存储结果

栈帧结构:

c 复制代码
[ebp+16] - 参数c
[ebp+12] - 参数b
[ebp+8]  - 参数a
[ebp+4]  - 返回地址
[ebp]    - 保存的ebp
[ebp-4]  - 局部变量result

4. 多个参数函数 funcManyParams (15个参数)

参数访问方式:

c 复制代码
mov eax, dword ptr [a1]       ; 读取a1
add eax, dword ptr [a2]       ; 加上a2
add eax, dword ptr [a3]       ; 加上a3
; ... 继续加上a4到a15
mov dword ptr [result], eax   ; 存储最终结果

栈帧结构:

c 复制代码
[ebp+64] - 参数a15 (最后一个参数)
...
[ebp+12] - 参数a2
[ebp+8]  - 参数a1 (第一个参数)
[ebp+4]  - 返回地址
[ebp]    - 保存的ebp
[ebp-4]  - 局部变量result

关键观察:

  1. 参数传递顺序 :在__cdecl调用约定下,参数从右向左压栈,所以最后一个参数在栈的最高地址。

  2. 参数访问方式 :所有参数都通过[ebp+offset]的方式从栈中访问,偏移量计算为:

    • 第一个参数:[ebp+8]
    • 第二个参数:[ebp+12]
    • 第n个参数:[ebp+8+4*(n-1)]
  3. 局部变量存储 :局部变量result存储在栈帧的[ebp-4]位置。

  4. 栈帧建立:每个函数开始都执行标准序言:

    c 复制代码
    push ebp
    mov ebp, esp
    sub esp, 0CCh  ; 为局部变量分配空间
  5. 栈帧清理:函数结束时恢复栈指针:

c 复制代码
 mov esp, ebp
 pop ebp

这种参数传递方式确保了函数能够正确访问调用者传递的所有参数,无论参数数量多少。

相关推荐
安全风信子2 小时前
45_混合专家模型:MoE架构详解
算法
ASIAZXO2 小时前
机器学习——聚类kmeans算法详解
算法·机器学习·聚类
HalvmånEver4 小时前
初学者入门 C++ map 容器:从基础用法到实战案例
开发语言·c++·学习·map
hello_lain4 小时前
9.1 简单排序(冒泡、插入)(排序(上))
c语言·数据结构·算法·排序算法
炬火初现4 小时前
Hot100——普通数组
算法·leetcode·职场和发展
啊我不会诶4 小时前
【数据结构】字典树
数据结构·算法
信奥卷王4 小时前
[GESP202403 五级] 成绩排序
数据结构·算法
saber_andlibert4 小时前
【C++】——new和delete与malloc和free的区别
c语言·c++
维度攻城狮5 小时前
C++中的多线程编程及线程同步
开发语言·c++·性能优化·多线程·线程同步