C++内存模型

发布时间 2023-09-28 16:24:47作者: MeYokYang

C++内存模型

存储持续性

C++存储持续性有以下类别:

  • 自动存储持续性:在函数定义中声明的变量(包括函数参数)。
  • 静态存储持续性:在函数定义外定义的变量和使用关键字static定义的变量。
  • 线程存储持续性(C++11):使用关键字thread_local定义的。生命周期与线程一样长。
  • 动态存储持续性:使用new运算符分配的内存将一直存在,直到使用delete运算符将其释放或程序结束为止。有时被称为自由存储/堆。

内存分配位置

  • 自动存储变量:分配到栈中,在程序执行其所属的函数/代码块时被创建,执行完函数/代码块时所使用的内存被释放。

  • 静态持续变量:分配到内存中固定位置,在程序整个运行过程中都存在。

    int global = 300;			// static duration, external linkage
    static int one_file = 50;	// static duration, internal linkage
    void funct1()
    {
        static int count = 0;	// static duration, no linkage
    }
    

    静态持续变量首先会被初始化为0,若有显示初始化,然后再进行静态初始化(编译器根据文件按内容算出值进行初始化)或动态初始化(编译后在初始化,通常是调用了函数)。局部静态持续变量并非像自动存储变量那样,它只初始化一次。

链接性

链接性为外部的变量称为外部变量,它们的存储持续性为静态。根据单定义规则,使用变量前需要声明,但只能定义一次。使用外部变量的文件中,必须先声明它,声明可分为两种:

  • 引用声明/声明:不给变量分配存储空间,因为它引用已有的变量。使用extern关键字,且不进行初始化,否则为定义声明,导致分配存储空间。
  • 定义声明/定义:他给变量分配存储空间。

如下示例,file01.cpp中全为定义,file02.cpp与file03.cpp全为声明。

// file01.cpp
extern int cats = 20;
int dogs = 22;
int fleas;

// file02.cpp
extern int cats;		
extern int dogs;

// file03.cpp
extern int cats;
extern int dogs;
extern int fleas;

注意:const修饰的外部变量的链接性为内部,可再次使用extern关键字将其变为外部。

extern const int states = 50;

作用域

  • 自动存储变量:声明处到代码块结束。
  • 静态存储变量:开头为声明处,若为外部链接和內部链接则结尾是文件末尾,若为无链接则结尾是代码块结束。

注意作用域可能会被同名的”相对局部变量“隐藏。

// file01.cpp
int errors = 20;

// file02.cpp
static int errors = 25;
void f()
{
    int errors = 30;
}

对于函数

函数的存储持续性都自动为静态,默认下链接性为外部,但可使用static关键字来修改为内部,使之只能作用于该文件。

static int private();
static int private()
{
    ...
}

内联函数不受单定义规则,意味着内联函数可放在头文件中被不同文件包含,各文件中均有定义,然而C++要求所有内联定义必须相同。

C++寻找函数的顺序:static函数在本身文件中寻找,否则先去所有程序文件中寻找,未找到去库文件中寻找。