zoukankan      html  css  js  c++  java
  • 面试题积累

    1、堆栈的区别

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

    (2)申请大小:能从栈获得的空间较小,堆事向高地址扩展的数据结构。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。

    (3)碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是一一对应的,以至于永远都不可能有一个内存块从栈中弹出。

    (4)分配方式:堆事动态分配的,没有静态分配的堆。栈有2中分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配有alloc函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。

    (5)分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的。

    2、简述你对UIView、UIWindow和CALayer的理解

      UIView:属于UIKit.framework框架,负责渲染矩形区域的内容,为矩形区域添加动画,响应区域的触摸事件,布局和管理一个或多个子视图。

      UIWindow:属于UIKit.framework框架,是一种特殊的UIView,通常在一个程序中只会有一个UIWindow,但可以手动创建多个UIWindow,同时加到程序里面。UIWindow在程序中主要起到三个作用:

        (1)、作为容器,包含app所要显示的所有视图。

        (2)、传递触摸消息到程序中的view和其他对象。

        (3)、与UIViewController协同工作,方便完成设备方向旋转的支持。

      CALayer:属于Quartz.framework框架,是用来绘制内容的,对内容进行动画处理依赖与UIView来进行显示,不能处理用户事件。UIView和CALayer是相互依赖的,UIView依赖CALayer提供内容,CALayer依赖UIView共容器显示绘制内容。

    3、ViewController的didReceiveMemoryWarning是在什么时候被调用的?默认的操作是什么?

      当程序接到内存警告时ViewController将会受到这个消息:didReceiveMemoryWarning。

      从iOS3.0开始,不需要重载这个函数,把释放内存的代码放到viewDidUnload中去。

      这个函数的默认实现是:检查controller是否可以安全地释放它的view,如果view可以被释放,那么这个函数释放view并调用viewDidUnload。重载这个函数来释放controller中使用的其他内存。但要记得调用这个函数的super实现来允许父类(一般是UIViewController)释放view。

      如果你的ViewController保存着view的子view的引用,那么,在早期的iOS版本中,你应该在这个函数中来释放这些引用。而在iOS3.0或更高版本中,你应该在viewDidUnload中释放这些引用。

    4、面向对象的三大特征,并作简单的介绍

      面向对象的三个基本特征:封装、继承、多态。

      封装是面向对象的特征之一,是对象和类概念的主要特征。封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的信息进行隐藏。隐藏对象的属性和实现细节,仅对外公开接口,提高代码安全性,封装程度越高,独立性越强,使用越方便。

      继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。通过继承创建的新类称为"子类"或"派生类",被继承的类称为"基类"、"父类"、"超类"。

      多态性:允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给他的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。

    5、我们说的object_c是动态运行时语言是什么意思?

      动态。主要是将数据类型的确定由编译时推迟到了运行时。这个问题其实涉及到两个概念,运行时喝多态。简单来说,运行时机制使我们直到运行时才去决定一个对象的类别,以及调用该类别对象指定方法。多态:不同对象以自己的方式响应相同的消息的能力叫做多态。意思就是假设生物类(life)都拥有一个相同的方法-eat;那人类属于生物,猫也属于生物,都继承了life后,实现各自的eat方法,但是调用时我们只需调用各自的eat方法,也就是不同的对象以自己的方式响应了相同的消息(响应了eat这个选择器)。因此也可以说,运行时机制是多态的基础。

    6、readwrite、readonly、assign、retain、copy、nonatomic、strong、weak属性的作用?并区别strong(强引用)、weak(弱引用)?什么情况下使用copy、assign和retain?

      readwrite 可读可写;需要生成getter方法和setter方法时。

      readonly 只读属性,只会生成getter方法,不会生成setter方法;不希望属性在类外改变。

      assign 赋值属性,setter方法将传入参数赋值给实例变量;仅设置变量时。

      retain 持有属性,setter方法将传入参数先保留,再赋值,传入参数的retaincount会+1。

      copy 赋值属性,setter方法将传入对象复制一份;需要完全一份新的变量时。

      nonatomic 非原子操作,决定编译器生成的setter、getter是否是原子操作,atomic表示多线程安全,一般使用nonatomic。

      assign用于简单数据类型,如NSInteger,double,bool。

      retain和copy用户对象,copy用于当a指向一个对象,b也想指向同样的对象的时候,如果用assign,a如果释放,再调用b会crash。如果用copy的方式,a和b各自有自己的内存,就可以解决这个问题。retain会使计数器+1,也可以解决assign的问题。另外:atomic和nonatomic用来决定编译器生成的getter和setter是否为原子操作。在多线程环境下,原子操作时必要的,否则有可能引起错误的结果。

    7、为什么很多内置类如UITableViewController的delegate属性都是assign而不是retain的?

      会引起循环引用--若是retain,再alloc一次之后,若release一次,会导致内存泄漏,若release两次会导致两个对象的dealloc嵌套执行,结果就是都没有执行成功,最后崩溃!所有的引用计数系统,都存在循环应用的问题,例如下面的引用关系:

      *对象a创建并引用到了对象b。

      *对象b创建并引用到了对象c。

      *对象c创建并引用到了对象b。

    这个时候b和c的引用计数分别是2和1。

    当a不再使用b,调用release释放对b的所有权,因为c还引用了b,所以b的引用计数为1,b不会被释放。

    b不释放,c的引用计数就是1,c也不会被释放。从此,b和c永远留在内存中。

    这种情况,必须打断循环引用,通过其他规则来维护引用关系。我们常见的delegate往往是assign方式的属性而不是retain的属性,赋值不会增加引用计数,就是为了防止delegation两端产生不必要的循环。

    如果一个UITableViewController对象a通过retain获取了UITableView对象b的所有权,这个UITableView对象b的delegate又是a,如果这个delegate是retain方式的,那基本上就没有机会释放这两个对象了。自己在设计使用delegate模式时,也要注意这点。

    8、OC中,与retain配对使用的方法是dealloc还是release,为什么?需要与alloc配对使用的方法是dealloc还是release,为什么?

      与retain配对使用的方法是release,因为retain使retainCount计数+1,release使retainCount计数-1;与retain语义相反的是release。

      与alloc配对使用的是release,因为:alloc是创建一个对象,dealloc使销毁一个对象。

    9、分析json、xml的区别?json、xml解析方式的底层是如何处理的?

    区别:

    (1)可读性方面:xml的可读性比较好。

    (2)可扩展方面:都具有很好的和扩展性。

    (3)编码难度:相对而言,json的编码比较容易。

    (4)解码难度:json的解码难度基本为零,xml需要考虑子节点和父节点。

    (5)数据体积:json相对于xml来讲,数据体积小,传递的速度更快些。

    (6)数据交互:json与JavaScript的交互更加方便,更容易解析处理,更好的数据交互。

    (7)数据描述:xml对数据描述性比较好。

    (8)传输速度:json的速度远远快于xml。

    JSON底层原理:遍历字符串中的字符,最终根据格式规定的特殊字符,比如{}号,[]号,:号等进行区分,{}号是一个字典的开始,[]是一个数组的开始。:号是字典的键和值的分水岭,最终乃是将json数据转化为字典,字典中值可能是字典、数组或字符串等。

    XML底层原理:XML解析常用的解析方法有两种:DOM解析和SAX解析。DOM采用建立树形结构的方式访问XML文档,而SAX采用的是事件模型。DOM解析把XML文档转化为一个包含其内容的树,并可以对树进行遍历。使用DOM解析器的时候需要处理整个XML文档,所以对性能和内存的要求比较高。SAX在解析XML文档的时候可以触发一系列的事件,当发现给定的tag的时候,它可以激活一个回调方法,告诉该方法制定的标签已经找到。SAX对内存的要求通常会比较低,因为它让开发人员自己来决定所要处理的tag,特别是当开发人员只需要处理文档中所包含的部分数据时,SAX这种扩展能力得到了跟好的体现。

    延伸:SAX与DOM的区别:

    (1)SAX处理的优点非常类似于流媒体的优点。分析能够立即开始,而不是等待所有的数据被处理,而且由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中,这对于大型文档来说是个巨大的优点。事实上,应用程序甚至不必解析整个文档;它可以在某个条件得到满足时停止解析。一般来说,SAX还比它的替代者DOM快许多。另一方面,由于应用程序没有以任何方式存储数据,使用SAX来更改数据或在数据流中往后移是不可能的。

    (2)DOM以及广义的基于树的处理具有几个优点。首先,由于树在内存中是持久的,因此可以修改它以便应用程序能对数据和结构作出更改。它还可以在任何时候在树中上下导航,而不是像SAX那样是一次性的处理。DOM使用起来也要简单得多。另一方面,在内存中构造这样的树涉及大量的开销,大型文件完全占用系统内存容量的情况并不鲜见。此外,创建一棵DOM树可能是一个缓慢的过程。

    (3)选择SAX还是选择DOM,这取决于这面几个因素:

      应用程序的目的:如果打算对数据作出更改并将他输出为XML,那么在大多数情况下,DOM是适当的选择,并不是说使用SAX就不能更改数据,但是该过程要复杂得多,因为你必须对数据的一份拷贝而不是对数据本身作出更改。

      数据容量:对于大型文件,SAX是更好的选择。数据将如何使用:如果只是数据中的少量部分会被使用,那么使用SAX来将该部分数据提取到应用程序中可能更好。另一方面,如果你知道自己以后会回头引用已处理过的大量信息,那么SAX也许不是恰当的选择。

      对速度的需要:SAX实现通常要比DOM实现更快。

    SAX和DOM不是相互排斥的,记住这点很重要。你可以使用DOM来创建SAX事件流,也可以使用SAX来创建DOM树,事实上,用于创建DOM树的大多数解析器实际上都使用SAX来完成这个任务。

    10、OC的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?

      OC的类不可以多重继承。可以实现多个接口,通过实现多个接口可以完成类似C++的多重继承。Category是类别,一般情况用分类好,用Category去重写类的方法,仅对本Category有效,不会影响到其他类与原有类的关系。

    11、#import和#include有什么区别?@class呢?#import<>和#import" "又有什么区别?

      #import是OC导入头文件的关键字,#include是C/C++导入头文件的关键字,使用#import头文件会自动只导入一次,不会重复导入,相当于#include和#pragma ince。@class告诉编译器某个类的声明,当执行时,才去查看类的实现文件,可以解决头文件的相互包含。#import<>用来包含系统的头文件,#include" "用来包含用户头文件。

    12、对于语NSString *obj = [[NSData alloc]init]; obj在编译时和运行时分别是什么类型的对象?

      编译时是NSString的类型,运行时是NSData类型的对象。

    13、常见的OC的数据类型有哪些,和C的基本数据类型有什么区别?如:NSInteger和int

      OC的数据类型有NSString,NSNumber,NSArray,NSMutableArray,NSData等等,这些都是class,创建后便是对象,而C语言的基本数据类型int,只是一定字节的内存空间,用于存放数值;NSInteger是基本数据类型,并不是NSNumber的子类,当然也不是NSObject的子类。NSInteger是基本数据类型Int或者Long的别名(NSInteger的定义typedef long NSInteger),它的区别在于,NSInteger会根据系统是32位还是64位来决定是本身是int还是Long。

    14、id 声明的对象有什么特性?

      id 声明的对象具有运行时的特性,即可以指向任意类型的Objcetive-C的对象。

    15、Objective-C如何对内存管理的,说说你的看法和解决方法?

      Objective-C的内存管理主要有三种方式ARC(自动内存计数)、手动内存计数、内存池。 

      (1) (Garbage Collection)自动内存计数:这种方式和java类似,在你的程序的执行过程中。始终有一个高人在背后准确地帮你收拾垃圾,你不用考虑它什么时候开始工作,怎样工作。你只需要明白,我申请了一段内存空间,当我不再使用从而这段内存成为垃圾的时候,我就彻底的把它忘记掉,反正那个高人会帮我收拾垃圾。遗憾的是,那个高人需要消耗一定的资源,在携带设备里面,资源是紧俏商品所以iPhone不支持这个功能。所以“Garbage Collection”不是本入门指南的范围,对“Garbage Collection”内部机制感兴趣的同学可以参考一些其他的资料,不过说老实话“Garbage Collection”不大适合适初学者研究。

    解决: 通过alloc – initial方式创建的, 创建后引用计数+1, 此后每retain一次引用计数+1, 那么在程序中做相应次数的release就好了。

      (2) (Reference Counted)手动内存计数:就是说,从一段内存被申请之后,就存在一个变量用于保存这段内存被使用的次数,我们暂时把它称为计数器,当计数器变为0的时候,那么就是释放这段内存的时候。比如说,当在程序A里面一段内存被成功申请完成之后,那么这个计数器就从0变成1(我们把这个过程叫做alloc),然后程序B也需要使用这个内存,那么计数器就从1变成了2(我们把这个过程叫做retain)。紧接着程序A不再需要这段内存了,那么程序A就把这个计数器减1(我们把这个过程叫做release);程序B也不再需要这段内存的时候,那么也把计数器减1(这个过程还是release)。当系统(也就是Foundation)发现这个计数器变 成员了0,那么就会调用内存回收程序把这段内存回收(我们把这个过程叫做dealloc)。顺便提一句,如果没有Foundation,那么维护计数器,释放内存等等工作需要你手工来完成。

    解决:一般是由类的静态方法创建的, 函数名中不会出现alloc或init字样, 如[NSString string]和[NSArray arrayWithObject:], 创建后引用计数+0, 在函数出栈后释放, 即相当于一个栈上的局部变量. 当然也可以通过retain延长对象的生存期。

      (3)(NSAutoRealeasePool)内存池:可以通过创建和释放内存池控制内存申请和回收的时机。

    解决:是由autorelease加入系统内存池, 内存池是可以嵌套的, 每个内存池都需要有一个创建释放对, 就像main函数中写的一样. 使用也很简单, 比如[[[NSString alloc]initialWithFormat:@”Hey you!”] autorelease], 即将一个NSString对象加入到最内层的系统内存池, 当我们释放这个内存池时, 其中的对象都会被释放。

    16、原子(atomic)跟非原子(non-atomic)属性有什么区别?

      (1)atomic提供多线程安全。是防止在写未完成的时候被另外一个线程读取,造成数据错误。

      (2)non-atomic:在自己管理内存的环境中,解析的访问器保留并自动释放返回的值,如果指定了 nonatomic ,那么访问器只是简单地返回这个值。

    17、内存管理的几条原则是什么?按照默认法则,哪些关键字生成的对象需要手动释放?在和property结合的时候怎样有效的避免内存泄漏?

      谁申请,谁释放;遵循CocoaTouch的使用原则。

      内存管理主要避免"过早释放"和"内存泄漏",对于"过早释放"需要注意@property设置特性时,一定要用对应性关键字,对于"内存泄漏",一定要申请了要负责释放,要细心。

      关键字alloc或new生成的对象需要手动释放。

      设置正确的property属性,对于retain需要在合适的地方释放。

  • 相关阅读:
    开源的UML建模工具
    leetcode 559. Maximum Depth of N-ary Tree
    leetcode 9. Palindrome Number
    暗网 tor溯源困难根因——用户的请求会在分布全球的主机随机跳转三次,最终才到达服务器,这就造成了溯源的极其困难
    leetcode 374. Guess Number Higher or Lower
    RDP协议暴力破解
    清华大学 pip 源
    暴力破解研究论文
    利用ModSecurity防御暴力破解
    IRC BOT原来是利用IRC下发C&C命令——在xx云环境遇到了,恶意软件开的是6666端口
  • 原文地址:https://www.cnblogs.com/GhostKZShadow/p/5099651.html
Copyright © 2011-2022 走看看