Effective Objective-C2.0 笔记(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_28285625/article/details/88646665

起源

Objecti-C与C++和Java等面向对象语言类似,不过很多方面有所差别。若是用过另一种面向对象语言,那么就能理解Objective-C所用的许多范式与模板了。然而语法上也许会显得陌生,因为该语言使用“消息结构”(message structure)而非“函数调用”(function calling)。Objective-C语言由SmallTalk演化而来,后者是消息型语言的鼻祖。消息与函数调用之间的区别看上去就像这样:

//Messaging (Objective-C)
Object *obj = [Object new];
[obj performWith:parameter1 and:parameter2];

//Function calling (C++)
Object *obj = new Object;
obj->perform(parameter1,parameter2);

关键区别在于:使用消息结构的语言,其运行时所应执行的代码由运行时环境来决定;而使用函数调用的语言,则由编译器决定。如果范例代码中调用的函数是多态的,那么在运行时(???)就要按照“虚方法表(virtual table)”来查出到底应该执行那个函数实现。而采用消息结构的语言,不论是否多态,总是在运行时才会查找所要执行的方法。实际上,编译器甚至不关心接受消息的对象是何种类型。接受消息的对象问题也要在运行时处理,其过程叫做“动态绑定”(dynamic binding),第11条会详述其细节。

virtual method table 是编程语言为实现“动态派发”(dynamic dispatch)或“运行时方法绑定”(runtime method binding)而采用的一种机制。

Objective-C是C的“超集”(superset),所以C语言中的所有功能的编写Objective-C代码依然使用。因此,必须同时掌握C与Objective-C这两门语言的核心概念,方能写出高效的Objective-C代码来。其中尤为重要的是要理解C语言的内存模型(memory model),这有助于理解Objective-C的内存模型及其“引用计数”(reference counting)机制的工作原理。若要理解内存模型,则需明白:Objective-C语言中的指针是用来指示对象的。想要声明一个变量,令其指代某个对象,可用如下语法:
NSString * someString = @“The string”;
这种语法基本上是照搬C语言的,它声明了一个名为someString的变量,其类型是NSString*。也就是说,此变量为指向NSString的指针。所有Objective-C语言的对象都是必须这样声明,因为对象所占内存总是分配在“堆空间”(heap space)中,而绝不会分配在“栈”(stack)上。不能再栈中分配Objective-C对象
NSString stackString; //error:interface type cannot be statically allocated
someString变量指向分配在堆里的某块内存,其中含有一个NSString对象。也就是说,如果再创建一个变量,另其指向同一地址,那么并不拷贝该对象,只是这两个变量会同时指向此对象:

NSString *someString = @"The string";
NSString *anotherString = someString;

只有一个NSString实例,然而有两个变量指向此实例。两个变量都是NSString型,这说明当前“栈帧”(stack frame)里分配了两块内存,每块内存的大小都能容下一枚指针(在32位架构的计算机上是4字节,64计算机上是8字节)。这两块内存里的只都一样,就是NSString实例的内存地址。
图1-1描述了此时的内存布局。存放在NSString实例中的数据含有代表字符串实际内容的字节。
1-1
图1-1 此内存布局图演示了一个分配在堆中的NSString实例,有两个分配在栈上的指针指向该实例。
分配在堆中的内存必须直接管理,而分配在栈上用于保存变量的内存则会在其栈帧弹出的时候自动清理。
Object-C将堆内存管理抽象出来了。不需用malloc及free来分配或释放对象所占内存。Objectiv-C运行期环境把这部分工作抽象为一套内存管理架构,名为“引用计数”。
在Objective-C代码中,有时候会遇到定义不含
的变量,它们可能使用“栈空间”(stack space)。这些变量所保存的不是Objective-C对象。不如CoreGraphics框架中CGRect就是个例子:

CGRect frame;
frame.origin.x = 0.0f;

CGRect是C结构体,其定义是:

struct CGRect{
CGPoint origin;
CGSize size;
};
typedef struct CGRect CGRect;

  整个系统框架都在使用这种结构体,因为如果改用Objective-C对象来做的话,性能会受影响。与创建结构体相比,创建对象还需要额外开销,例如分配及释放堆内存等。如果只需保存int,float,char等“非对象类型”(nonobject type),那么通常使用CGRect这种结构体就可以了
  • Objective-C为C语言添加了面向对象特性,是其超集。Objective-C使用了动态绑定的消息结构,也就是说,在运行时才会检查对象类型。接受一条消息之后,究竟应执行何种代码,有运行期环境而非编译器决定。
  • 理解C语言的核心概念有助于写好Objective-C程序。尤其要掌握内存模型与指针。

猜你喜欢

转载自blog.csdn.net/qq_28285625/article/details/88646665