面向对象与内存管理

面向对象5大原则(solid)(立方体)

  • s(single-resposibility-principle):单一原则
    一个类,最好只做一件事情,单一的原则可以看做是低耦合,高内聚在面向对象原则上的引申述,将职责定义为引起变化得原因,以高内聚来减少引起变化的原因。
  • o(open-close-principle):开放封闭原则,软件实体该是可扩展的,而不可修改的。也是对扩展开放,对修改封闭。
  • l(LisKov-substituion-principle)里氏原则:子类必须能够扩展基类,这一个思想体现了对继承机制的约束规范,只有子类能替换基类时,才能保证系统在运行期间能够识别子类,这是保证继承复用的基础。
  • i(interface-segregation):接口隔离原则:使用多个小的专门的接口,而不要使用一个大的接口
  • (Dependecy-incersion-principle)依赖倒置原则:依赖与抽象,具体而言就是高层模块不依赖与底层模块,二者都依赖于抽象;抽象不依赖与具体,具体依赖于抽象。

内存管理

程序可执行问题的结构
一个程序的可执行文件在内存中的结果,从大的角度可以分为两个部分:只读部分和可读写部分。只读部分包括程序代码(.text)和程序中的常量(.rodata)。可读写部分(也就是变量)大致可以分成下面几个部分:

  • .data: 初始化了的全局变量和静态变量
  • .bss: 即 Block Started by Symbol, 未初始化的全局变量和静态变量(这个我感觉上课真的没讲过啊我去。。。)
  • heap: 堆,使用 malloc, realloc, 和 free 函数控制的变量,堆在所有的线程,共享库,和动态加载的模块中被共享使用
  • stack: 栈,函数调用时使用栈来保存函数现场,自动变量(即生命周期限制在某个 scope 的变量)也存放在栈中。

data 和 bss 区

这两个区经常放在一起说,因为他们都是用来存储全局变量和静态变量的,区别在于 data 区存放的是初始化过的, bss 区存放的是没有初始化过的,例如:

int val = 3;
char string[] = “Hello World”;
这两个变量的值会一开始被存储在 .text 中(因为值是写在代码里面的),在程序启动时会拷贝到 .data 去区中。

而不初始化的话,像下面这样:

static int i;
这个变量就会被放在 bss 区中。

答疑一 静态变量和全局变量

这两个概念都是很常见的概念,又经常在一起使用,很容易造成混淆。

全局变量:在一个代码文件(具体说应该一个 translation unit/compilation unit))当中,一个变量要么定义在函数中,要么定义在在函数外面。当定义在函数外面时,这个变量就有了全局作用域,成为了全局变量。全局变量不光意味着这个变量可以在整个文件中使用,也意味着这个变量可以在其他文件中使用(这种叫做 external linkage)。当有如下两个文件时;

a.c

include <stdio.h>

int a;

int compute(void);

int main()
{
    a = 1;
    printf("%d %d\n", a, compute());
    return 0;
}

b.c

int a;

int compute(void)
{
    a = 0;
    return a;
}

在 Link 过程中会产生重复定义错误,因为有两个全局的 a 变量,Linker 不知道应该使用哪一个。为了避免这种情况,就需要引入 static。

静态变量: 指使用 static 关键字修饰的变量,static 关键字对变量的作用域进行了限制,具体的限制如下:

  • 在函数外定义:全局变量,但是只在当前文件中可见(叫做 internal linkage)
  • 在函数内定义:全局变量,但是只在此函数内可见(同时,在多次函数调用中,变量的值不会丢失)
  • (C++)在类中定义:全局变量,但是只在此类中可见
    对于全局变量来说,为了避免上面提到的重复定义错误,我们可以在一个文件中使用 static,另一个不使用。这样使用 static 的就会使用自己的 a 变量,而没有用 static 的会使用全局的 a 变量。当然,最好两个都使用 static,避免更多可能的命名冲突。

注意:’静态’这个中文翻译实在是有些莫名其妙,给人的感觉像是不可改变的,而实际上 static 跟不可改变没有关系,不可改变的变量使用 const 关键字修饰,注意不要混淆。

Bonus 部分 —— extern: extern 是 C 语言中另一个关键字,用来指示变量或函数的定义在别的文件中,使用 extern 可以在多个源文件中共享某个变量,例如这里的例子。 extern 跟 static 在含义上是“水火不容”的,一个表示不能在别的地方用,一个表示要去别的地方找。如果同时使用的话,有两种情况,一种是先使用 static,后使用 extern ,即:

static int m;
extern int m;

这种情况,后面的 m 实际上就是前面的 m 。如果反过来:

extern int m;
static int m;

这种情况的行为是未定义的,编译器也会给出警告。

答疑二 程序在内存和硬盘上不同的存在形式

这里我们提到的几个区,是指程序在内存中的存在形式。和程序在硬盘上存储的格式不是完全对应的。程序在硬盘上存储的格式更加复杂,而且是和操作系统有关的,具体可以参考这里。一个比较明显的例子可以帮你区分这个差别:之前我们提到过未定义的全局变量存储在 .bss 区,这个区域不会占用可执行文件的空间(一般只存储这个区域的长度),但是却会占用内存空间。这些变量没有定义,因此可执行文件中不需要存储(也不知道)它们的值,在程序启动过程中,它们的值会被初始化成 0 ,存储在内存中。

本文由2篇文章整理而成~由于时间较长为找到原文出处,请谅解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值