目录
有关头文件
有关语法
有关内存分配与编译
(本章节中例子都是用 VS2005 编译调试的)
有关头文件
C++头文件命名约定:
c++旧式风格 以.h结尾 iostream.h c++可以
c旧式风格 以.h结尾 math.h 同上
c++新式风格 没有扩展名 iostream c++可以使用命名空间
转换后c 加上前缀c无扩展名cmath 同上
定义头文件时候注意:
当文件用尖括号包含时从一个或多个系统文件中找,用双引号包含时,应在当前目录查找,头文件不区分大小写
头文件应该包含内容:
- 函数原型
- 使用define或const定义的符号常量
- 结构体声明
- 模板声明
- 内联函数
- 引用的外部变量
[返回目录]
有关语法
C++源代码风格:
- 每一条语句由‘;’结束
- 每一行一条语句
- 函数都以一个花括号开始,以一个花括号结束,这两花括号各占一行
- 函数中语句都相对于花括号进行缩进
- 与函数名称相关的圆括号周围没有空白
复合语句:
复合语句用{ },把多个语句组合起来,在其后无需加';',因为'}'表示语句以结束
1 for(int i=1; i<10 ; i++)
2 // 下面就是符合语句
3 {
4 cout<<"现在测试循环,循环为10次"<<endl;
5 cout<<"当前为第 "<<i+1<<" 次循环"<<endl;
6 }
换行处理:
处理长字符串时有个基本(但不常用)的方法,这个方法依赖很少使用程序格式化的特性;在一行末尾加一个反斜符号(‘\’)可以将此行和下一行当做同一行处理
1 cout<<"输入数 N 要满足10 <= N \ // '\' 在这里起连接下一行的作用
2 <= 10^9,请从新";
[返回目录]
有关内存和编译
关于变量分配的内存------------------------------------
C/C++编译的程序占用内存分配的几部分:
- 栈区
由编译器自动分配释放的,存放着函数的参数值,局部变量的值,其操作方式类似于数据结构中的栈(申请)速度快,但程序员无法控制
- 堆区
由程序员分配释放,程序员不释放程序结束时可能回收,分配方式类似键表(申请速度慢,易产生内存碎片)
- 全局区/静态区
全局变量与静态变量的存储是放一块的,初始化全局变量在一块区域内,未初始化的静态变量在相邻的另一块区域内,程序结束后由系统释放,内存在整个运行期间都存在
- 文字常量区
常量字符串就是放在这里,程序结束后由系统释放
- 程序代码区
存放函数体的二进制代码
堆与栈区别:(参考链接)
- 申请方式:
- 栈: 由系统自动分配。 例如,声明在函数中一个局部变量 int b; 系统自动在栈中为b开辟空间
- 堆: 需要程序员自己申请,并指明大小,在C++中用 new 这个关键字来开辟用户自定需要动态创建的变量
- 申请后系统的响应:
- 栈: 只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出
- 堆: 首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表 中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。 另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中
- 申请大小的限制:
- 栈: 在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意 思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。
- 堆: 堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大
- 申请效率的比较:
- 栈: 由系统自动分配,速度较快。但程序员是无法控制的。
- 堆: 是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便. 另外,在WINDOWS下,最好的方式是用VirtualAlloc分配内存,他不是在堆,也不是在栈是 直接在进程的地址空间中保留一块内存,虽然用起来最不方便。但是速度快,也最灵活
- 堆和栈中的存储内容:
- 栈: 在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可 执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈 的,然后是函数中的局部变量。注意静态变量是不入栈的。 当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地 址,也就是主函数中的下一条指令,程序由该点继续运行
- 堆: 一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容由程序员安排
- 小结: 堆和栈的区别可以用如下的比喻来看出:
○ 使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就 走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小
○ 使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大
例子:
1 int a = 0; //全局变量 a 存放在全局区(静态区)中
2 static int *p1; //静态全局指针 p1 存放在全局区(静态区)中
3 void main()
4 {
5 int b; // b 变量存放在栈中
6 char *p2; //指针 p2 存放在栈中
7 static int c =0; //静态局部 c 变量数据存放在全局区(静态区)中
8 p1 = new int(20); //p1 指向的的数据(即 20)存放在堆区中
9 p2 = new char('a'); //p2 指向的数据(即 'a')存放在堆区中
10 delete p1;
11 delete p2;
12 system("pause");
13 }
关于编译----------------------------------------------
静态联编动态联编:
- 联编定义 将源代码中的函数调用解释为执行特定函数代码块被称为函数名联编
- 静态联编/早期联编 在编译的过程中进行联编(体现: 函数重载)
- 动态联编/晚期联编 编译前必须生成能够在程序运行时选择正确的虚方法的代码(体现: 类的虚方法)
[返回目录]
外部参考链接:
C++ 对象的内存布局(上)
C++ 对象的内存布局(下)