https://blog.csdn.net/u013007900/article/details/79338653
一个由C/C++编译的程序占用的内存分为以下几个部分:
栈区(stack)— 由编译器自动分配释放,存放函数的参数值,局部变量的值等。其 *** 作方式类似于数据结构中的栈。堆区(heap) — 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS( *** 作系统)回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放。文字常量区 —常量字符串就是放在这里的。程序结束后由系统释放。程序代码区—存放函数体的二进制代码。
int a=0; 全局初始化区 char *p1; 全局未初始化区 int main() { int b; //栈 char s[]="abc"; //栈 char *p2; //栈 char *p3="123456"; //123456/0在常量区,p3在栈上。 static int c =0;//全局(静态)初始化区 p1 = (char *)malloc(10); //分配得来得10和20字节的区域就在堆区 p2 = (char *)malloc(20); strcpy(p3,"123456"); //123456/0放在常量区,编译器可能会将它与p3所指向的"123456" 优化成一个地方。 }头文件
不要将函数定义或变量声明放到头文件中,如果同一程序的其他两个文件包含了该头文件,此时同一个程序将包含同一个函数的两个定义,即多重声明问题,这会导致错误。头文件常包含以下内容:
函数原型(函数声明)宏定义;#define或const定义的符号常量。结构声明类声明模板声明内联函数
源代码文件用于具体实现,即头文件中所声明的函数或类的具体实现。
注意,只需将源代码文件加入到项目中,而不用加入头文件。这是因为#include指令管理头文件。另外,不要使用#include来包含源代码文件,这样做将导致多重声明。
https://blog.csdn.net/nei504293736/article/details/90200066
模板类的分离问题:
声明和实现都写到.h文件中或者,声明写到.h中,实现写到.cpp中,同时在.cpp文件中声明具体的模板类(显式实例化)
https://www.jianshu.com/p/bd2e05aabf7a
https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file
存储持续性、作用域和链接有4中内存方案:
自动存储持续性,在函数定义中声明的 变量(包括函数参数)的存储持续性是自动的。它们在程序开始执行其所属的函数或代码块时被创建,在执行完函数或代码块时,它们使用的内存被释放。静态存储持续性,在函数定义外定义的变量和使用关键字static定义的变量的存储持续性都为静态。它们在程序整个运行过程中都存在。线程存储持续性,对于多线程来说,如果变量是使用关键字thread_local声明的,则其生命周期与所属的线程一样长。动态存储持续性,用new运算符分配的内存将一直存在,直到使用delete运算符将其释放或程序结束为止。这种内存的存储持续性为动态,有时被称为自由存储(free store)或堆(heap)。
作用域(scope)描述了名称在文件的多大范围内可见。可分为局部和全局,作用域为局部的变量只在定义它的代码块中可用,作用域为全局的变量在定义位置到文件结尾之间都可用。
链接性(linkage)描述了名称如何在不同单元间共享。链接性为外部的名称可在文件间共享,链接性为内部的名称只能由一个文件中的函数共享。
静态持续变量与static程序不会使用栈或者其他来管理静态变量,而是编译器会分配固定的内存块来存储静态变量,这样这些变量在整个程序执行期间一直存在。另外如果没有显式地初始化静态变量,编译器将把它设置为默认值。
C++为静态存储持续性变量提供了3种链接性:
外部链接性,可在其他文件中访问内部链接性,只能在当前文件中访问无链接性,只能在当前函数或代码块中访问
int global = 10; //静态持续,外部链接 static int one_file = 50; //静态持续,内部链接 void fun1(int n) { static int count = 0; //静态持续,无链接性 int llama = 0; }
所有静态持续变量在整个程序执行期间都存在。fun1()中声明的变量count的作用域是局部且没有链接性,但是该变量会一直存留在内存中;global和one_file的作用域都为整个文件,而one_file的链接性为内部只能在本文件中使用它,而global的链接性为外部,因此可在其他程序文件中使用它。
extern与static链接性为外部的变量通常简称为外部变量,它们的存储持续性为静态,作用域为整个文件。外部变量是在函数外部定义的,其也可被称为全局变量。
单定义规则(One Definition Rule, ODR):变量只能由一次定义。C++提供了两种变量声明。一种是定义声明(defining declaration)或简称为定义(definition),它给变量分配存储空间;另一种声明是引用声明(referencing declaration)或简称为声明(declaration),它不给变量分配存储空间,因为它引用已有的变量。引用声明使用关键字extern,且不进行初始化。
引用声明使用关键字extern,且不进行初始化;否则,声明为定义,导致分配存储空间。如果要在多个文件中使用外部变量,只需在一个文件中包含该变量的定义(当定义规则),但在使用该变量的其他所有文件中,都必须使用关键字extern声明它。
//file1.cpp int a; //定义,默认为0 static int b = 4; // 定义,因为初始化了 const int c = 5; extern const int d = 6; extern int e = 7; int fun1(int m, int n) { //... } //file2.cpp extern int a, d, e; //声明,因为有extern且未初始化 int b, c; // static, const的链接性均为内部 int fun1(int, int); //函数声明的extern可省略其他说明符和限定符
const
声明为const的变量必须在声明的时候就初始化,并且一旦初始化后,其值就不可改变,且其声明一般是放在头文件中。const变量的链接性为内部。不过可以在定义时使用extern修饰来覆盖默认的内部链接性,将该变量的链接性为外部,
extern const int states = 50; // definition with external linkage
此时,必须在所有使用该常量的文件中使用extern关键字来声明它,这与常规外部变量不同,定义常规外部变量时,不必使用extern关键字,但在使用该变量的其他文件中必须使用extern。
mutable
mutable修饰的变量表明其无论如何是可改变的。比如一个const对象,其成员变量不可变,此时若声明某个成员变量是mutable的,则它依旧可以通过该const对象来改变该成员变量的值。
函数和链接性所有函数的存储持续性都为静态的,即在整个程序执行期间都存在。默认情况下,函数的链接性为外部,即可以在多个文件中共享,但是在另一个文件中可以不使用extern关键字来声明函数原型,而可以直接声明函数原型即可。如果使用static关键字修饰函数,则其链接性将变为内部,此时其只能在一个文件中使用而不能在其他文件中声明和使用,必须在函数原型和函数定义中都使用该关键字,此时如果外部有同名函数,该静态函数将覆盖外部同名函数,就同局部变量覆盖全局变量一样。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)