zoukankan      html  css  js  c++  java
  • 李洪强经典面试题34

    1.static 关键字的作用:

      (1)函数体内 static 变量的作用范围为该函数体,不同于 auto 变量,该变量的内存只被分配一次, 因此其值在下次调用时仍维持上次的值;

      (2)在模块内的 static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;

      (3)在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;

      (4)在类中的 static 成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;

      (5)在类中的 static 成员函数属于整个类所拥有,这个函数不接收 this 指针,因而只能访问类的static成员变量。

      2.线程与进程的区别和联系?

      进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。

      程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。

      线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。

      但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

      3.堆和栈的区别

      管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak。

      申请大小:

      栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。

      这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在 WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。

      因此,能从栈获得的空间较小。

      堆:堆是向高地址扩展的数据结构,是不连续的内存区域。

      这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。

      由此可见,堆获得的空间比较灵活,也比较大。

      碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。

      对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出。

      分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。

      动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。

      分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。

      堆则是C/C++函数库提供的,它的机制是很复杂的。

      4.什么是键-值,键路径是什么

      模型的性质是通过一个简单的键(通常是个字符串)来指定的。视图和控制器通过键来查找相应的属性值。

      在一个给定的实体中,同一个属性的所有值具有相同的数据类型。键-值编码技术用于进行这样的查找—它是一种间接访问对象属性的机制。

      键路径是一个由用点作分隔符的键组成的字符串,用于指定一个连接在一起的对象性质序列。

      第一个键的性质是由先前的性质决定的,接下来每个键的值也是相对于其前面的性质。

      键路径使您可以以独立于模型实现的方式指定相关对象的性质。通过键路径,您可以指定对象图中的一个任意深度的路径,使其指向相关对象的特定属性。

      5.目标-动作机制

      目标是动作消息的接收者。一个控件,或者更为常见的是它的单元,以插座变量(参见"插座变量"部分)的形式保有其动作消息的目标。

      动作是控件发送给目标的消息,或者从目标的角度看,它是目标为了响应动作而实现的方法。

      程序需要某些机制来进行事件和指令的翻译。这个机制就是目标-动作机制。

      6.objc的内存管理

      如果您通过分配和初始化(比如[[MyClass alloc] init])的方式来创建对象,您就拥有这个对象,需要负责该对象的释放。这个规则在使用NSObject的便利方法new 时也同样适用。

      如果您拷贝一个对象,您也拥有拷贝得到的对象,需要负责该对象的释放。

      如果您保持一个对象,您就部分拥有这个对象,需要在不再使用时释放该对象。 反过来。

      如果您从其它对象那里接收到一个对象,则您不拥有该对象,也不应该释放它(这个规则有少数的例外,在参考文档中有显式的说明)。

      7.自动释放池是什么,如何工作

      当您向一个对象发送一个autorelease消息时,Cocoa就会将该对象的一个引用放入到最新的自动释放池。

      它仍然是个正当的对象,因此自动释放池定义的作用域内的其它对象可以向它发送消息。

      当程序执行到作用域结束的位置时,自动释放池就会被释放,池中的所有对象也就被释放。

      1.ojc-c 是通过一种"referring counting"(引用计数)的方式来管理内存的, 对象在开始分配内存(alloc)的时候引用计数为一。

      以后每当碰到有copy,retain的时候引用计数都会加一, 每当碰到release和autorelease的时候引用计数就会减一,如果此对象的计数变为了0, 就会被系统销毁.

      NSAutoreleasePool 就是用来做引用计数的管理工作的,这个东西一般不用你管的.

      autorelease和release没什么区别,只是引用计数减一的时机不同而已,autorelease会在对象的使用真正结束的时候才做引用计数减一.

      8.类工厂方法是什么

      类工厂方法的实现是为了向客户提供方便,它们将分配和初始化合在一个步骤中,返回被创建的对象,并进行自动释放处理。

      这些方法的形式是+ (type)className...(其中 className不包括任何前缀)。

      工厂方法可能不仅仅为了方便使用。它们不但可以将分配和初始化合在一起,还可以为初始化过程提供对象的分配信息。

      类工厂方法的另一个目的是使类(比如NSWorkspace)提供单件实例。

      虽然init...方法可以确认一个类在每次程序运行过程只存在一个实例,但它需要首先分配一个“生的”实例,然后还必须释放该实例。

      工厂方法则可以避免为可能没有用的对象盲目分配内存。

      9.单件实例是什么

      Foundation 和 Application Kit 框架中的一些类只允许创建单件对象,即这些类在当前进程中的唯一实例。

      举例来说,NSFileManager 和NSWorkspace 类在使用时都是基于进程进行单件对象的实例化。

      当向这些类请求实例的时候,它们会向您传递单一实例的一个引用,如果该实例还不存在,则首先进行实例的分配和初始化。

      单件对象充当控制中心的角色,负责指引或协调类的各种服务。

      如果类在概念上只有一个实例(比如 NSWorkspace),就应该产生一个单件实例,而不是多个实例;

      如果将来某一天可能有多个实例,您可以使用单件实例机制,而不是工厂方法或函数。

      10.动态绑定

      在运行时确定要调用的方法

      动态绑定将调用方法的确定也推迟到运行时。在编译时,方法的调用并不和代码绑定在一起,只有在消实发送出来之后,才确定被调用的代码。

      通过动态类型和动态绑定技术,您的代码每次执行都可以得到不同的结果。运行时因子负责确定消息的接收者和被调用的方法。

      运行时的消息分发机制为动态绑定提供支持。当您向一个动态类型确定了的对象发送消息时,运行环境系统会通过接收者的isa指针定位对象的类,并以此为起点确定被调用的方法,方法和消息是动态绑定的。

      而且,您不必在Objective-C 代码中做任何工作,就可以自动获取动态绑定的好处。

      您在每次发送消息时,特别是当消息的接收者是动态类型已经确定的对象时,动态绑定就会例行而透明地发生。

      11.obj-c的优缺点

      objc优点:

      1) Cateogies

      2) Posing

      3) 动态识别

      4) 指标计算

      5)弹性讯息传递

      6) 不是一个过度复杂的 C 衍生语言

      7) Objective-C 与 C++ 可混合编程

      缺点:

      1) 不支援命名空间

      2) 不支持运算符重载

      3)不支持多重继承

      4)使用动态运行时类型,所有的方法都是函数调用,所以很多编译时优化方法都用不到。(如内联函数等),性能低劣。

      12.sprintf,strcpy,memcpy使用上有什么要注意的地方

      strcpy是一个字符串拷贝的函数,它的函数原型为strcpy(char dst, c****t char *src);

      将 src开始的一段字符串拷贝到dst开始的内存中去,结束的标志符号为 ,由于拷贝的长度不是由我们自己控制的,所以这个字符串拷贝很容易出错。

      具备字符串拷贝功能的函数有memcpy,这是一个内存拷贝函数,它的函数原型为memcpy(char dst, c***t char src, unsigned int len);

      将长度为len的一段内存,从src拷贝到dst中去,这个函数的长度可控。但是会有内存叠加的问题。

      sprintf是格式化函数。将一段数据通过特定的格式,格式化到一个字符串缓冲区中去。

      sprintf格式化的函数的长度不可控,有可能格式化后的字符串会超出缓冲区的大小,造成溢出。

  • 相关阅读:
    【转】CUDA5/CentOS6.4
    【转】centos 6.4 samba 安装配置
    【转】Install MATLAB 2013a on CentOS 6.4 x64 with mode silent
    【转】Getting xrdp to work on CentOS 6.4
    【VLFeat】使用matlab版本计算HOG
    Unofficial Windows Binaries for Python Extension Packages
    March 06th, 2018 Week 10th Tuesday
    March 05th, 2018 Week 10th Monday
    March 04th, 2018 Week 10th Sunday
    March 03rd, 2018 Week 9th Saturday
  • 原文地址:https://www.cnblogs.com/LiLihongqiang/p/5947231.html
Copyright © 2011-2022 走看看