zoukankan      html  css  js  c++  java
  • c++之内存模型

    c++在程序执行时,将内存大方向分为四个区:

    • 代码区:存放函数体的二进制代码,由操作系统进行管理;
    • 全局区:存放全局变量和静态变量以及常量;
    • 栈区:由编译器自动分配释放,存放函数的参数值、局部变量等;
    • 堆区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收;

    内存四区的意义:不同区域存放的数据,赋予不同的生命周期,给我们更灵活的编程。

    程序运行前:

    在程序编译后,生成了.exe可执行程序,未执行程序前分为两个区域:

    代码区:

    • 存放cpu执行的机器指令
    • 代码区是共享的,共享的目的是对于频繁被执行的程序,只需要在内存中存有一份代码即可;
    • 代码区是只读的,使其只读的原因是防止程序意外修改了它的指令;

    全局区:

    • 全局变量和静态变量存放于此;
    • 全局区还包含了常量区:字符串常量和其它常量也存放于此。
    • 该区域的数据在程序结束后由系统释放;
    #include <iostream>
    using namespace std;
    //全局变量
    int c = 10;
    int d = 10;
    //const修饰的全局变量
    const int h = 10;
    
    int main() {
        //局部变量
        int a = 10;
        int b = 10;
        //静态变量
        static int e = 10;
        static int f = 10;
        //const修饰的局部变量
        const int g = 10;
        cout << "局部变量a的地址为:" << (int)&a << endl;
        cout << "局部变量b的地址为:" << (int)&b << endl;
        cout << "全局变量c的地址为:" << (int)&c << endl;
        cout << "全局变量d的地址为:" << (int)&d << endl;
        cout << "静态变量e的地址为:" << (int)&e << endl;
        cout << "静态变量f的地址为:" << (int)&f << endl;
        //字符串常量
        cout << "字符串常量的地址为:" << (int)&"hello" << endl;
        cout << "const修饰的局部变量的地址为:" << (int)&g << endl;
        cout << "const修饰的全局变量的地址为:" << (int)&h << endl;
        system("pause");
        return 0;
    }

    输出:

    我们可以发现什么?

    局部变量位于一块内存,全局变量、静态变量和常量位于另一块内存。

    程序运行后:

    栈区:由编译器自动分配释放,存放函数的参数值,局部变量等;

    #include <iostream>
    using namespace std;
    int* func(int b) {
    
        //局部变量存储在栈区,程序结束后会由系统释放;
        //形参也会存储在栈区;
        b = 10;
        int a = 10;
        //不要返回局部变量的地址
        return &a;
    }
    
    int main() {
        //接收func的返回值
        int* p = func();
        //第一次可以打印正确是因为编译器做了保留
        cout << *p << endl;
        //第二次就不会保留了
        cout << *p << endl;
        system("pause");
        return 0;
    }

    输出:

    堆区:由程序员分配释放,若程序员不释放,则程序结束时由系统释放。在c++中主要利用new在堆区开辟内存。

    #include <iostream>
    using namespace std;
    int* func(){
        //利用new在堆中开辟内存
        //指针本质也是局部变量,存放在栈上,指针保存的数据是存放在堆区
        int* p = new int(10);
        return p;
    }
    
    int main() {
        int* p = func();
        cout << *p << endl;
        cout << *p << endl;
        system("pause");
        return 0;
    }

    输出:

    new操作符:

    c++利用new操作符在堆区开辟数据:堆区开辟的数据,由程序员手动开辟,手动释放,释放使用delet操作符。

    #include <iostream>
    using namespace std;
    int* func(){
        //利用new在堆中开辟内存
        //指针本质也是局部变量,存放在栈上,指针保存的数据是存放在堆区
        int* p = new int(10);
        return p;
    }
    
    int main() {
        int* p = func();
        cout << *p << endl;
        cout << *p << endl;
        delete p;
        cout << *p << endl;
        system("pause");
        return 0;
    }

    在释放了内存之后,再访问就会报访问权限错误。

    //在堆中开辟内存存储数组
    int* arr = new int[10];
    for(int i=0;i<10;i++){
        arr[i] = i;
    }
    //释放内存
    delete[] arr
  • 相关阅读:
    TSQL笔记4:表
    C#笔记26: 与非托管代码交互操作
    C#笔记22:多线程之停止或取消线程
    C#笔记25:比较和排序(IComparable和IComparer以及它们的泛型实现)
    TSQL笔记7:临时表和表变量
    TSQL笔记6:GO
    WPF快速指导9:WPF中的属性(依赖项属性)
    TSQL笔记2:INSERT、UPDATE和DELETE
    C#笔记23:多线程之Task(并行编程)
    云计算读书笔记(一)
  • 原文地址:https://www.cnblogs.com/xiximayou/p/12084315.html
Copyright © 2011-2022 走看看