1、内存布局:
Linux下32位环境的用户空间内存分布情况如图,
一个典型的程序运行步骤:
- 操作系统创建进程后把控制权交给这个神秘的入口函数;
- 入口函数对运行库和程序运行环境进行初始化(包括堆分配,I/O资源的分配,线程,全局变量构造等);
- 入口函数调用main函数,执行程序主体
- main返回之后,回到入口函数,清理堆,关闭I/O,析构全局变量,然后结束进程。
程序运行以后的内存布局情况为: 2^32 = 4G 的虚拟地址空间
0x00000000 3G用户空间
(128M)
0x08048000 内核直接将程序加载到线性地址为0x08048000开始的位置(.text放置的起始位置)
(.text )
(.data)
(.bss )
(heap)向上增长
(stack)向下增长
0xC0000000 1G内核空间
0xF0000000
对用户空间的“默认”区域进行分析:
内存空间的默认区域分析
2、主要区别:(C++所特有的方面)
- 参数带默认值的函数:
形参/部分形参设置默认值,在调用函数时通过参数传递情况决定形参实际得到默认值/实参值。
注: 实参与形参的结合是从左至右进行,因此指定默认值的参数必须放在形参列表的首位。
函数声明:
void func(int x = 10);
函数调用:
func(); //传入默认值10
func(20); //传入指定值20
- 内联函数 inline:
定义:定义在类内的函数。
编译过程:在函数调用点把函数的代码全部展开。
动机:消除函数调用时的时间开销。
方式:类内直接定义/类外加inline。
int ret = sum(10, 20); --> ret = 10+20;//内联函数
(1)与宏区别:
. 宏在编译之前的预处理阶段;
. 内联处理是更安全的宏,有语法等信息检查,可以调试检查。
(2)与普通函数区别:
.内联函数没有标准的函数栈桢开辟和回退(调用函数开销小),不产生符号;
.仅本文件可见,因此要写在头文件中
(3)与static函数区别:
.作用域相同:均今当前文件可用;
. static函数仍有栈桢开辟与回退;
.符号产生不同:static函数产生符号local,但链接器仅处理符号global(普通函数产生),因此链接器不处理,不会产生重复
- 函数重载:
函数名相同,但参数列表不同。(与返回值类型无关)
(1)静多态:函数重载,模板
动多态:继承里的多态(虚函数)
(2)重载必须处于同一作用域,否则不属于重载。
(编译器先搜索局部,再全局)
(3)调用重载函数时类型模糊的数据会根据运算符优先级转换匹配
- const
c 修饰为常变量,定义同时初始化,不能作为左值存在,可以通过指针进行修改。
c++
修饰为常量:初始值为立即数,“更安全的宏替换”;
修饰为常变量:初始值为变量(编译阶段不确定)。
常量在引用一个编译阶段不明确的值时(被初始为另一个变量)会退化为常变量。
仅当前文件可见local,定义处前加extern,改为global。
- 引用
通过指针解引用和引用赋值二者底层相同。
定义引用变量不开辟内存,引用变量同被引用变量地址相同。
条件:
(1)必须初始化
(2)初始化的值必须要能取地址
(3)引用不能改变
(4)访问引用变量,即访问被引用变量内存。
动态内存分配:
new:(1)开辟内存(2)调用构造函数
delete:(1)调用析构函数(2)释放内存