一、C++函数的返回值在内存中的传递过程
1. 按值返回
当函数按值返回时,返回值会在栈上进行复制。整个过程如下:当函数被调用时,会在调用栈上维护一个独立的栈帧空间,相关的参数和局部变量在栈上分配内存。函数内部计算返回值,并将结果存储在它自己的栈帧中。当函数执行到 return
语句时,返回值将被复制到调用函数的栈帧中。此时,编译器可能会将返回值用调用函数栈帧中的一个临时变量来接收这个返回值。函数返回后,调用的栈帧将被清理(栈指针向下移动),局部变量的内存被释放。
2. 按引用返回
当函数按引用返回(即返回一个引用或指向存储在某处的对象的指针)时,返回的内存地址将被直接使用,而不是复制值。这种方式不会引入额外的复制成本,但在使用时需要小心,尤其要确保引用的生命周期有效,例如不能返回局部变量的引用,可以返回静态局部变量的引用,因为一旦函数返回,局部变量的内存将被释放,返回的引用将指向一块无效的内存。与按值返回相同,参数和局部变量会在栈上分配内存。当执行到 return
语句时,程序实际上返回了变量或对象的内存地址。调用者可以通过此地址直接访问 。
栈中分配了变量或对象的空间。函数返回时,返回的是一个指向该变量或对象 的引用(即它的内存地址)。
二、 什么是虚拟内存,为什么要使用虚拟内存,虚拟内存可能比物理内存大吗
虚拟内存
进程中只能访问虚拟内存地址,操作系统会把虚拟内存地址翻译成真实的内存地址,这种内存管理方式,称为虚拟内存。操作系统为每个进程分配一套独立的虚拟地址,每个进程访问自己的虚拟地址,互不干涉,操作系统会提供将虚拟内存地址和物理地址映射的机制。如果程序要访问虚拟地址的时候,由操作系统转换成不同的物理地址,这样不同的进程运行的时候,写入的是不同的物理地址,这样就不会冲突了。
虚拟内存有以下几个重要的作用和好处:
- 扩展可用内存: 虚拟内存使得每个进程可以访问比物理内存更大的内存空间。当物理内存不足时,虚拟内存可以将一部分不常用的数据暂时存储在磁盘上,以释放出物理内存供其他进程使用。这样,系统能够同时运行更多的程序,提升了系统的整体运行能力。
- 进程隔离和保护: 虚拟内存为每个进程提供了独立的地址空间,使得进程之间相互隔离。这样,一个进程不能直接访问其他进程的内存空间,保护了进程的数据和代码的安全性。如果一个进程出现了异常或崩溃,只会影响到该进程本身,而不会对其他进程造成影响。
- 简化内存管理: 虚拟内存使得内存管理更加简化。操作系统可以在物理内存和磁盘之间进行数据交换,将内存调度和分配操作集中在物理内存上,而不需要关心具体的物理地址。这样简化了内存分配和释放的操作,提高了内存管理的效率。
- 内存共享和进程通信: 虚拟内存允许多个进程共享同一部分内存,这样不同的进程可以轻松地共享数据和信息,实现进程间的通信和协作。例如,多个进程可以共享同一块内存区域,实现高效的数据交换和共享资源
总而言之,虚拟内存为系统提供了更高的内存使用效率、更好的进程隔离和保护、更简化的内存管理以及使得操作系统能够更好地更灵活的进程通信等好处,运行和管理多个应用程序。
同时,虚拟内存可以大于物理内存。虚拟内存也提供了一种内存扩展机制,使得系统能够运行更多的程序,而不会因为物理内存不足而导致程序崩溃。举个例子来说,假设一个系统有4GB的物理内存和一个 32 位的进程。虚拟内存可以将这个进程的地址空间分为多个页面 (通常是4KB一组) 。当进程需要访问某个页面时,操作系统会将其加载到物理内存中并更新进程的页表,如果物理内存不足,则可能需要将某些不常用的页面置换出来,供其他进程使用。这样,每个进程都能够拥有4GB的地址空间,而不受实际物理内存容量的限制。