内存的具体分类 每个区块的特点

内存

程序运行的时候,操作系统分配4G大小的虚拟内存,其中有一个G的大小是操作系统的内核区,无法使用,3G栈区。数据结构的栈和这个栈不是同一个东西。

(数据结构:栈,MAP)MAP存放键值对  map存放在堆区

栈下面是共享,堆,全局区静态区,常量区(存函数)。

函数的名字就是函数的地址


1.栈区(存放 局部变量+函数参数)

特点:

空间少

自动释放             (例如:函数内部定义的变量在函数结束时会自动释放内存,无需手动返回。

                                          超出作用域后,编译器会自动回收

访问速度快


2.全局区(存放 全局变量)

特点:

访问的时候 就近原则:局部大于全局

“局部大于全局”是编程中的一个常见原则,主要指的是在某些情况下,局部变量的作用范围和优先级高于全局变量。这一原则的具体含义可以从以下几个方面理解:

1. **作用域**:局部变量是在函数或块内部定义的变量,其作用范围仅限于该函数或块。而全局变量是在整个程序中都可以访问的变量。当局部变量和全局变量同名时,局部变量会覆盖全局变量,在局部范围内使用局部变量。

2. **优先级**:在函数内部,如果存在与全局变量同名的局部变量,函数内部的代码会优先使用局部变量。这意味着在函数内部对该变量的操作不会影响全局变量的值,除非显式地使用全局变量的引用。

3. **避免命名冲突**:使用局部变量可以避免与全局变量的命名冲突,从而提高代码的可读性和可维护性。它可以帮助程序员更好地管理变量的生命周期和作用域。

4. **内存管理**:局部变量的生命周期仅限于函数的执行时间,函数结束后自动释放内存,而全局变量在程序运行期间一直存在。因此,局部变量有助于更有效地管理内存。

总之,“局部大于全局”强调了在编程时局部变量的优先使用,鼓励开发者尽量使用局部变量来避免不必要的复杂性和潜在的错误。

生命周期:从程序的开始到程序的结束

注意事项:

多个cpp文件,全局变量发生重定义,extern关键字声明

int a;
void fun(int qq)
{
    int a;
    a=2;//这里访问的是局部的
}
extern int pointer;//声明pointer这个变量,表示这个变量已经存在
//导入自己写的头文件用双引号,在自己项目里面寻找,尖括号是在系统里面寻找,下载路径里面寻找
//导入就相当于把那个文件里面的代码复制粘贴过来了
//而且文件.h可以动,.cpp不能随便动,只有一个。
//导入的语句可以写多次#icnlude什么什么,效果一样的

3.堆区 (存放 动态数组 链表 图 树)

特点:
不会自动释放,需要手动释放内存

容量大

访问速度比栈区慢

#include<iostream>
using namespace std;

void test01()
{
    int n;
    int* p1=NULL;
    cin >> n;
    if (n > 0) p1 = (int*)malloc(n * sizeof(int));//在堆区申请int类型内存
    if (p1)free(p1);
}
int main()
{
    //申请堆区内存使用malloc;malloc(需要申请的字节个数);
    //返回值:mallo会将申请到的堆区内存的首地址返回
    // 如果malloc申请内存失败,则返回空
    //malloc注意手动释放
    char* p = (char*)malloc(500);//一个字符一个字节//malloc的返回值需要强制转换
    p[3] = 'a';//p是数组首元素地址,p[3]==*(p+3)
    cout << p[3];
    free(p);
    /*
    * 原理:
    * p在栈区,因为p是局部变量,(函数参数和局部变量都在栈区)
    * char* p栈区
    * (char*)malloc(500);堆区
    * free(p)释放p指向的堆区内存
    */

    
    return 0;
}

4.常量区(存放 各种常量 字符串常量 函数常量 常量数组 整型常量 浮点常量 字符常量 地址常量)

特点:

不可修改 只读

int num[3]={1,2,3}

num++报错,地址常量不让被修改

左值是什么?有名字的就是左值

右值是什么?没有名字的就是右值

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;


int main()
{
    int num[3] = { 1,2,3 };
    int* b = num;//num是地址常量不能修改
    return 0;
}

在以上代码中,`num` 是一个数组,它的名字 `num` 在表达式中代表数组的首地址,因此 `int* b = num;` 是正确的。这行代码将 `num` 数组的首地址赋值给指针 `b`。

但是,关于你提到的 `num` 是“地址常量不能修改”的说法需要澄清:

1. **`num` 是一个数组名**:在 C++ 中,数组名(如 `num`)在大多数情况下会被转换为指向其第一个元素的指针。这个指针是一个常量,意味着你不能改变 `num` 指向的地址。例如,`num = nullptr;` 会导致编译错误,因为你不能修改数组名的值。

2. **`*b = 2;` 是合法的**:通过指针 `b` 来访问和修改数组的内容是合法的。`*b` 实际上是 `num[0]`,所以执行 `*b = 2;` 会将数组的第一个元素修改为 `2`,这在语法上是正确的。代码如下:

   ```cpp
   int num[3] = { 1, 2, 3 };
   int* b = num; // b 指向 num 数组的首地址
   *b = 2; // 这将把 num[0] 的值修改为 2
   ```

   这段代码执行后,`num` 数组的内容将变为 `{ 2, 2, 3 }`。

### 总结
- `num` 是一个数组名,表示数组的首地址,不能被修改。
- 通过指针 `b` 可以访问和修改 `num` 数组中的元素,`*b = 2;` 是合法的,并会改变 `num` 数组的内容。


5.静态区(存放 静态的局部变量和静态的全局变量)

malloc p1 = (int*)malloc(n * sizeof(int));//在堆区申请int类型内存 p1这个变量在栈区 需要申请的内存字节个数

对返回值进行强制转换 本来的返回值是void*类型,释放用free

特点:

静态变量的生命周期:从程序开始到程序结束

静态变量只被初始化一次

void func() {
    static int count = 0; // 静态局部变量
    count++;
    std::cout << count << std::endl;
}

int main() {
    func(); // 输出 1
    func(); // 输出 2
    func(); // 输出 3
    return 0;
}

静态局部变量 作用域 :当前的{}内

存放静态变量static

  • 静态变量不会被分配到函数栈中。即使它们是在函数内部定义的(作为静态局部变量),它们也不会在函数调用时被创建或销毁,而是一直存在于静态区中。

静态全局变量 作用域:当前文件 ,不发生重定义,不同函数里面可以重复定义

这句话的意思是关于静态全局变量的作用域和链接性。我们可以逐步拆解来理解:

### 1. 静态全局变量的定义

静态全局变量是在文件的顶部定义的,使用 `static` 关键字修饰的全局变量。它的定义形式如下:

```cpp
static int myStaticVar = 0; // 静态全局变量
```

### 2. 作用域:当前文件

- **作用域**:静态全局变量的作用域仅限于定义它的源文件。这意味着在该文件之外,其他文件无法访问或引用这个静态全局变量。即使在其他文件中有同名的全局变量,它们也不会产生冲突,因为静态全局变量在其他文件中是不可见的。

  例如,如果你在 `file1.cpp` 中定义了一个静态全局变量 `static int myVar;`,那么这个变量在 `file1.cpp` 中可以被访问,但在 `file2.cpp` 中是不可见的,无法访问或使用。

### 3. 不发生重定义

- **不发生重定义**:由于静态全局变量的链接性是内部链接(internal linkage),这意味着即使在同一文件中定义了多个同名的静态全局变量,它们也不会发生重定义的错误,因为它们的作用域是局部的,只在定义它们的文件中有效。

  例如:

  ```cpp
  // file1.cpp
  static int myVar = 1; // 第一个静态全局变量

  void func() {
      static int myVar = 2; // 这是另一个静态全局变量,与上面的不同
  }
  ```

  在这个例子中,`file1.cpp` 中的 `myVar` 在全局作用域和 `func` 函数中都有定义,但它们是两个不同的变量,互不影响。

### 总结

- **静态全局变量的作用域**:仅限于定义它的文件,其他文件无法访问。
- **不发生重定义**:在同一文件中,即使有同名的静态全局变量,它们也不会发生冲突,因为它们的作用域是局部的。

这种特性使得静态全局变量在模块化编程中非常有用,可以避免命名冲突,同时又能在需要时保持状态。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值