c++内存分区


c++核心编程

即面向对象编程

面向对象由原来的程序等于数据结构+算法转变为对象等于数据结构+算法

而程序等于对象+对象+…消息

消息是对对象的控制

内存分区模型

c++程序在执行时,内存分为4大区

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

意义:
不同区域存放的数据,赋予不同的生命周期,更*灵活

程序运行前

程序编译后,生成exe可执行文件,未执行该程序前分为两个区域

代码区
存放cpu执行的机器指令(二进制代码)

​ 特点:

1. 共享:目的在于频繁执行的程序,只要在内存中有一份代码即可
 2. 只读:目的在于防止程序意外修改了它的指令

全局区

全局变量与静态变量存放于此

还包含常量区,有字符串常量与其他常量存放于此

该区域的数据在程序结束后由操作系统释放

# include 
#include 
using namespace std;

//全局变量
//函数体外,g--global 
int g_a = 10;
int g_b = 10;
 
const int c_g_a = 10;
const int c_g_b = 10;

int main()
{
    //创建普通变量 
    //只要变量写在函数体中,(main也算),就算普通变量 
    int a = 10;
    int b = 10; 
    cout << "a地址" << &a << endl;
    cout << "b地址" << &b << endl;
    //a地址0x70fe1c
    //b地址0x70fe18//相差4 
    cout << "g_a地址" << &g_a << endl;
    cout << "g_b地址" << &g_b << endl;
    //g_a地址0x472010
    //g_b地址0x472014//相差4
    //然而全局与局部的地址开头部分相差很大,说明两者不在一个内存区 
    
    //静态变量 在普通变量前加static
    static int s_a = 10;
    static int s_b = 10;
    cout << "s_a地址" << &s_a << endl;
    cout << "s_b地址" << &s_b << endl;
    //s_a地址0x472018
    //s_b地址0x47201c
    //由此看出静态与全局内存紧挨在一起分配
    
    //常量 
        //字符串常量
    cout << "字符串常量地址" << &"hello world" << endl;
    //字符串常量地址0x48803b
    //与静态和全局有一定距离,但并不远
    
        //const修饰变量
        //1.const修饰全局变量,全局区 
        cout << "c_g_a地址" << &c_g_a << endl;
        cout << "c_g_b地址" << &c_g_b << endl;
        //c_g_a地址0x488064
        //c_g_b地址0x488068
        //与字符串常量很近,但还是有一定距离 
        
        //2.const修饰局部变量,不在全局区(带局部都不在全局区里)
        const int c_l_a = 10;//local 
        const int c_l_b = 10; 
        cout << "c_l_a地址" << &c_l_a << endl;
        cout << "c_l_b地址" << &c_l_b << endl;
        //c_l_a地址0x70fe14
        //c_l_b地址0x70fe10
        
    system("pause");
    return 0;
 } 

程序运行后

栈区

​ 由编译器自动分配释放,存放函数参数值,局部变量等

​ 注意:不要返回局部变量的地址,栈区开辟的数据由编译器自动释放

 # include 

using namespace std;

int * func()
{
    int a = 10;
    return &a;
}
int main()
{
    int * p = func();
    cout << *p << endl;//[Warning] address of local variable 'a' returned [-Wreturn-local-addr]
    cout << *p << endl;//只保留一次,第二次为乱值 
    system("pause");
    return 0;
}

堆区

new在堆区开辟

new操作符

new int [5];//开辟整型数组

new int(100);//开辟一个整型空间,初值为100

int * p = new int [5];//new 返回的是指针

delete [] p;释放p指向的空间即new int [5];

定义类与对象

类是对象的抽象,而对象是类的实例

类与结构体很多性质相似

类可以看作一种数据类型,而对象就是变量

形式:

class 类名:

{

​ private:

​ 私有的数据和成员函数;

​ public:

​ 公有的数据和成员函数;//即接口

}

private是私有的,public是公有的,默认私有

类外定义函数是一种好习惯

格式:返回类型 类名 ::函数名(参数)::表示作用域

对于类中一些简单的成员函数可以用inline将其作为内置函数,减少调用时间,inline写在返回类型前面,就将main函数中的函数调用语句直接替换为函数语句

一个对象所占用的空间只与其数据成员所占据的空间相关

成员函数不占用存储空间,不同的对象使用的是同一段代码

类与对象的使用

构造函数实现数据成员初始化

构造函数与类同名,不具有任何类型,不返回任何值,在建立对象时对数据成员赋初值,不能被用户调用

类名()

{

}

可以用一个类对象,初始化另一个类对象,而不调用构造函数。

带参数的构造函数,在定义对象的时候给出实参

也可以

类名 :: 构造函数名(形参1,形参2,…):成员初始化{};

对于数组要在函数体中进行操作

在声明构造函数时还可以指定默认值

析构函数

是在撤销对象占用的内存前完成一些清理操作

-类名

是用户最后一次使用对象后的操作,(释放前),先释放的,先执

类的时候用**::,对象的时候用.**

指向成员函数的指针

数据类型名 (类名 :: * 指针变量名 )(参数表)//括号不可省略

指针变量名 = & 类名 :: 成员函数名

复制构造函数

类名 对象2(对象1)


文章作者: linta
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 linta !
  目录