Skip to content

Commit

Permalink
Translate code changes and add examples to "CPP-Memory-Allocation-Exp…
Browse files Browse the repository at this point in the history
…lained.md" and "Cpp-Namespace-Demystified.md"
  • Loading branch information
jamiesun committed Mar 21, 2024
1 parent cc7720b commit f7d425e
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 1 deletion.
90 changes: 90 additions & 0 deletions _posts/2024-03-21-CPP-Memory-Allocation-Explained.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,114 @@ keywords: c++, memory-allocation

> 专业解释: 栈是一种先入后出(LIFO)的内存结构,用于存储局部变量和函数调用的控制信息。在C++中,当函数被调用时,函数参数和局部变量会在栈上分配空间,且这一分配过程是自动的,编译器会为我们管理这些内存。内存的分配与释放速度极快,但栈的大小通常是有限制的,且不易调整。一旦函数执行完成,其栈帧(对应的内存块)就会被销毁,相关的内存空间被释放。这种自管理特性意味着栈内存通常不会引起内存泄漏问题。然而,栈的空间有限,对大量数据的存储或者复杂数据结构的创建可能不够用,在这些情况下,通常会选择堆内存分配。
```cpp
void foo() {
int a = 10; // 'a' 存储在栈上
char b = 'x'; // 'b' 也存储在栈上
}

int main() {
foo(); // 当foo函数被调用时, 'a' 和 'b' 被分配在栈上.
// 当foo函数返回时, 'a' 和 'b' 被自动释放.
return 0;
}
```

## 动态房间(堆)

堆内存像是酒店的长期套房,适合那些需要自定义服务和长期住宿的客人。当你的需求变化多端,需要更多的空间或者要住得更久时,你可以请求一个堆房间。这就像是你向酒店提出特殊要求,他们为你找到一个合适的房间,大小和住宿时长都是你自己定的。不过,不要忘了在离开时退房(释放内存),否则这个房间就会一直空着,造成空间浪费。

> 专业解释:堆内存是由程序运行时动态分配的一块内存区域,提供了灵活的内存大小配置和生命周期管理。不同于栈内存的自动分配和释放,堆内存的分配通常通过 `new` 操作符,在 C++ 中进行,而释放则通过 `delete` 操作符。堆内存适合存储生命周期长于函数调用或者大小超过栈限制的数据。尽管堆提供了更大的灵活性,其管理却完全依赖于程序员,这意味着必须显式地分配和释放内存,以防止内存泄漏或野指针的问题。堆的动态特性允许程序在运行时根据需要扩展或缩减数据结构,但这也意味着相比于栈操作,堆内存分配和释放的过程相对缓慢,且容易产生内存碎片。因此,专业的开发者需要权衡使用堆内存的时机,以兼顾性能和灵活性。
```cpp
#include <iostream>

int main() {
// 动态分配单个整数的内存
int *ptr = new int;

// 给动态分配的整数赋值
*ptr = 42;

// 输出动态分配的整数的值
std::cout << "Value of dynamic integer: " << *ptr << std::endl;

// 释放之前分配的内存
delete ptr;

// 重要:将指针设置为NULL,避免野指针
ptr = nullptr;

return 0;
}
```

## 共享空间(静态存储区)

静态存储区就像是酒店的共享会议室,可以被任何人使用,并且一直保持着开放状态。这部分内存用于存放全局变量和静态变量,一旦分配,在程序的整个生命周期内都是有效的。这类似于你在酒店预订了一个共享空间,无论你在不在,空间都会一直为你保留,并且在你整个逗留期间都可以使用。

> 专业解释:静态存储区是程序运行期间持续存在的内存部分,用来存储程序的全局变量和静态变量;一旦这些变量被初始化,它们会在程序的整个生命周期内保持分配状态,直到程序终止。这种存储方式保证了变量的值在函数调用之间是持久的,不会像自动存储的局部变量那样在其作用域结束时失效。
```cpp
// 静态存储区的简单使用示例

#include <iostream>

// 全局变量 - 存储在静态存储区
int globalVariable = 10;

// 静态局部变量 - 也存储在静态存储区
void staticLocalExample() {
static int staticLocalVariable = 50;
std::cout << "Static local variable: " << staticLocalVariable << std::endl;
staticLocalVariable++;
}

int main() {
std::cout << "Global variable: " << globalVariable << std::endl;

// 调用函数,显示静态局部变量的值
staticLocalExample(); // 输出: Static local variable: 50
staticLocalExample(); // 输出: Static local variable: 51

// 再次显示全局变量的值
// 它在整个程序执行期间保持不变,除非被修改
std::cout << "Global variable: " << globalVariable << std::endl;

return 0;
}
```

## 专用 VIP 区(寄存器)

寄存器是最快速的房间,像是酒店的特快专用通道。这些内存非常有限,只用于存储最频繁访问的数据。不是所有客人都能住在这里,只有 VIP(非常重要的程序部件)才有资格。

> 专业解释: 寄存器是 CPU 内的非常小但速度极快的数据存储区域,用于存储那些需要被快速访问和处理的操作数和指令。在程序执行过程中,最常用的变量和最频繁执行的计算结果往往被放置在寄存器中,以提高程序的执行效率。寄存器的数量和大小是固定的,由 CPU 架构决定。编译器通常会在编译过程中进行寄存器分配优化,以确保重要的计算可以尽可能地利用这些高速内存资源。由于寄存器的高速特性,它们通常用于实现快速的算术运算、函数调用的参数传递和局部变量存储,但受限于数量,它们不能用于大量数据的存储。
```cpp
// 寄存器存储示例 - 适用于理解基础概念,实际中寄存器的分配由编译器优化决定

#include <iostream>

int main() {
register int fastVariable = 10; // 建议编译器尽可能将 'fastVariable' 存储在寄存器中

std::cout << "The value of register variable: " << fastVariable << std::endl;

// 由于 'fastVariable' 可能存储在寄存器中,我们不能获取它的内存地址
// 下面的代码如果取消注释, 将会导致编译错误:
// std::cout << "The address of register variable: " << &fastVariable << std::endl;

return 0;
}

// 输出: The value of register variable: 10
```

在这个示例中,变量 `fastVariable` 被建议存储在寄存器中,以便快速访问。关键字 `register` 是向编译器的一个建议,告诉它我们希望这个变量能够存放在寄存器中。然而,是不是真的会被存放在寄存器中,以及哪一个寄存器会被使用,取决于编译器的优化决策。

请注意,在现代C++编译器中,`register` 关键字基本上已经过时,因为现代编译器的优化算法足够智能,能够自主决定哪些变量应该存储在寄存器中。实际编码时,我们很少(如果不是从不)需要手动指示编译器使用寄存器,因为编译器会为我们做出最优决策。

## 现实中的 C++内存管家

要成为 C++的内存管家,你必须理解每种房型的规则:栈是自动的,快速但有限制;堆是灵活的,但需要手动管理;静态是持久的,但是共享的;而寄存器是最快的,却也是最稀缺的资源。你要做的就是正确地分配这些房间,确保程序的客人有一个舒适的住宿体验!
Expand Down
1 change: 0 additions & 1 deletion _posts/2024-03-21-Cpp-Namespace-Demystified.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ namespace Physics {
理解命名空间的用途与最佳实践,能够帮助开发者更加高效地组织和维护他们的C++代码库,从而减少错误并增强代码的重用性。
## 扩展思考
关于C++命名空间的使用价值和最佳实践,以下问题可以引导您深入思考:
Expand Down

0 comments on commit f7d425e

Please sign in to comment.