程序内存布局

引入

以32位系统为例,最大支持内存为2^32,即2 ^ 30 * 4 = 4G
内存分为内核态和用户态

内核态

其中1G内存可分给系统应用,即内核态

用户态

另外3G内存分配给用户态
用户态由高地址到低地址又可划分为几个层次

栈区

栈区内存的占用是由高地址(0x3f3f3f3f)到低地址(0x00000000)进行分配的,由操作系统进行控制,定义变量时地址是由系统分配的

共享库

如果栈发生了溢出,一些变量可能会放到此处

堆区

内存由低地址(0x00000000)往高地址(0x3f3f3f3f)分配,由程序员控制,

printf("%p", *(new int(1)));
//打印为00000001

由输出结果可以看出只有程序员使用了堆,堆区才能被内存分配

全局/静态区

存放静态(static)变量和全局变量

文字常量区(只读段)

只读段就是指类似const一样只允许调用而不允许修改
文字常量区存放的是const修饰的变量和字符串常量

程序代码区(只读段)

存放定义的函数,仅仅是存放函数而不是函数内部实现过程

值得注意的细节

假设有数组arr1,和数组arr2
对数组arr1 + 1得到的就是arr[1]的地址,偏移了一个单位长度,而对&arr1+1则是偏移了整个数组的长度

int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("%p\n", arr1);
printf("%p\n", arr1 + 1);
printf("%p\n", &arr1 + 1);
/*
000000A18070F8C8
000000A18070F8CC
000000A18070F8F0
*/

因为是int类型数组,所以每次偏移一个单位长度移动4个字节,可以看到arr1 到arr1 + 1刚好一个单位长度,而&arr1 + 1则有10个单位长度

由const修饰的局部变量还是放在了栈区,因为局部变量的生命周期比const所在的常量区要短,const的生命周期被限制,只能放在栈区

生命周期是指一个变量在执行时存在的时间,局部变量因为是在函数中定义,在函数调用完成后就会销毁,因此局部变量的生命周期很短

比较特殊的
例如static修饰的变量无论是全局变量还是局部变量都是放在静态区
int *pint = new int(1);//由new或malloc分配的空间必定放在堆区,而pint还是根据全局还是局部来判断在哪个区

对象入门

面向过程

/按照事物发展的过程逐步进行
为了一个程序的执行,可能需要调用一个已经实现的函数
这个函数内部还会调用其他的函数,新调用的函数还会调用其他的函数
在调用函数(算法)的过程中,会进行传参,这个参数就是一个数据结构
面向过程的程序就是由算法与数据结构结合使用的

面向对象

N个对象之间的交互,是客观现实世界正常的运行方式
A对象发出动作产生消息,B对象接受消息再发出对应动作
A对象在产生消息时,可能也存在C,D等对象也收到消息并发出动作
这一过程就像现实世界中各种生物之间的交互,具有多样性,也就是多态
面向对象的精髓就是消息传递

对象的创建关键–抽象

对某一整体共同的特征属性和行为,将其划分为同一类,这一类就是一个对象
共同的特征属性就可以认为是类的数据成员,行为就是类的函数成员

类的定义

class Person{
public://默认为public,类之外可直接访问
void pay();
//protected://保护的访问权限,交给子类(派生类)访问

private://不允许类之外访问
string id;
int money;

};

一般来说特征属性都是放在private内,行为都是放在public内

类的使用

class computer{
public:
void setbrand(const string & brand)
{
_brand = brand;
}
void setprice(const int & price)
{
_price = price;
}
void print()
{
cout<<_brand<<endl;
cout<<_price<<endl;
}
private:
string _brand;
int _price;
};

void test()
{
computer c1;
//类的调用可以像结构体一样
c1.setbrand("HUAWEI");
c1.setprice("10999");
c1.print();
}

为了代码规范,数据成员一般以 ‘ _ ‘ 开头

可以看到,在对象定义完成后,主函数主要是在调用对象