最全的iOS面試題及答案
iOS面試小貼士
———————————————回答好下面的足夠了-------------------------------------
多線程、特別是NSOperation 和 GCD 的內(nèi)部原理。
運行時機制的原理和運用場景。
SDWebImage的原理硝清。實現(xiàn)機制乍狐。如何解決TableView卡的問題肚逸。
block和代理的认境,通知的區(qū)別硕淑。block的用法需要注意些什么课竣。
strong,weak置媳,retain于樟,assign,copy nomatic 等的區(qū)別拇囊。
設(shè)計模式迂曲,mvc,單利寥袭,工廠路捧,代理等的應用場景关霸。
單利的寫法。在單利中創(chuàng)建數(shù)組應該注意些什么杰扫。
NSString 的時候用copy和strong的區(qū)別队寇。
響應值鏈。
NSTimer 在子線程中應該手動創(chuàng)建NSRunLoop 章姓,否則不能循環(huán)執(zhí)行佳遣。
UIScrollView和NSTimer組合做循環(huán)廣告圖輪播的時候有一個屬性可以控制當上下滾動tableview的時候廣告輪播圖依然正常滾動。
Xcode最新的自動布局凡伊。零渐。。這個很多公司都用系忙。盡量自學下相恃。
git ,和svn的用法笨觅。拦耐。。git的幾個命令簡單的記下见剩。杀糯。。
友盟報錯可以查到具體某一行的錯誤苍苞,原理是什么固翰。
Instrument 可以檢測 電池的耗電量、和內(nèi)存的消耗羹呵。的用法骂际。
動畫CABaseAnimation CAKeyAni…. CATrans….. CAGoup…. 等熟悉。冈欢。
ARC的原理歉铝。
自己寫過什么自定義控件就最好了。凑耻。
———————————————回答好上面的足夠了-------------------------------------
__block和__weak修飾符的區(qū)別其實是挺明顯的:
1.__block不管是ARC還是MRC模式下都可以使用太示,可以修飾對象,還可以修飾基本數(shù)據(jù)類型香浩。
2.__weak只能在ARC模式下使用类缤,也只能修飾對象(NSString),不能修飾基本數(shù)據(jù)類型(int)邻吭。
3.__block對象可以在block中被重新賦值餐弱,__weak不可以。
tableView 滑動卡的問題主要是因為:從緩存中或者是從本地讀取圖片給UIImage的時候耗費的時間。需要把下面的兩句話放到子線程里面:
NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:app.icon]]; //得到圖像數(shù)據(jù)
UIImage *image = [UIImage imageWithData:imgData];
把UIImage賦值給圖片的時候在主線程膏蚓。
子線程不能更新UI 所有的UI跟新都是主線程執(zhí)行了猖败。手指滑動屏幕了〗翟剩或者屏幕的某個方法執(zhí)行了恩闻。
子線程里面加入NSTimer 的時候需要 手動添加NSRunloop 否則不能循環(huán)。
單利里面添加 NSMutableArray 的時候剧董,防止多個地方對它同時便利和修改的話幢尚,需要加原子屬性。并且用strong翅楼,尉剩,,并且寫一個遍歷和修改的方法毅臊。加上鎖理茎。 Lock UnLock
__weakViewController* weakSelf =self;
GCD里面用 __weak 防止內(nèi)存釋放不了,循環(huán)引用管嬉。
二皂林、SDWebImage內(nèi)部實現(xiàn)過程
入口 setImageWithURL:placeholderImage:options: 會先把 placeholderImage 顯示,然后 SDWebImageManager 根據(jù) URL 開始處理圖片蚯撩。
進入 SDWebImageManager-downloadWithURL:delegate:options:userInfo:础倍,交給 SDImageCache 從緩存查找圖片是否已經(jīng)下載 queryDiskCacheForKey:delegate:userInfo:.
先從內(nèi)存圖片緩存查找是否有圖片,如果內(nèi)存中已經(jīng)有圖片緩存胎挎,SDImageCacheDelegate 回調(diào) imageCache:didFindImage:forKey:userInfo: 到 SDWebImageManager沟启。
SDWebImageManagerDelegate 回調(diào) webImageManager:didFinishWithImage: 到 UIImageView+WebCache 等前端展示圖片。
如果內(nèi)存緩存中沒有犹菇,生成 NSInvocationOperation 添加到隊列開始從硬盤查找圖片是否已經(jīng)緩存德迹。
根據(jù) URLKey 在硬盤緩存目錄下嘗試讀取圖片文件。這一步是在 NSOperation 進行的操作揭芍,所以回主線程進行結(jié)果回調(diào) notifyDelegate:胳搞。
如果上一操作從硬盤讀取到了圖片,將圖片添加到內(nèi)存緩存中(如果空閑內(nèi)存過小沼沈,會先清空內(nèi)存緩存)流酬。SDImageCacheDelegate 回調(diào) imageCache:didFindImage:forKey:userInfo:。進而回調(diào)展示圖片列另。
如果從硬盤緩存目錄讀取不到圖片,說明所有緩存都不存在該圖片旦装,需要下載圖片页衙,回調(diào) imageCache:didNotFindImageForKey:userInfo:。
共享或重新生成一個下載器 SDWebImageDownloader 開始下載圖片。
圖片下載由 NSURLConnection 來做店乐,實現(xiàn)相關(guān) delegate 來判斷圖片下載中艰躺、下載完成和下載失敗。
connection:didReceiveData: 中利用 ImageIO 做了按圖片下載進度加載效果眨八。
connectionDidFinishLoading: 數(shù)據(jù)下載完成后交給 SDWebImageDecoder 做圖片解碼處理腺兴。
圖片解碼處理在一個 NSOperationQueue 完成,不會拖慢主線程 UI廉侧。如果有需要對下載的圖片進行二次處理页响,最好也在這里完成,效率會好很多段誊。
在主線程 notifyDelegateOnMainThreadWithInfo: 宣告解碼完成闰蚕,imageDecoder:didFinishDecodingImage:userInfo: 回調(diào)給 SDWebImageDownloader。
imageDownloader:didFinishWithImage: 回調(diào)給 SDWebImageManager 告知圖片下載完成连舍。
通知所有的 downloadDelegates 下載完成没陡,回調(diào)給需要的地方展示圖片。
將圖片保存到 SDImageCache 中索赏,內(nèi)存緩存和硬盤緩存同時保存盼玄。寫文件到硬盤也在以單獨 NSInvocationOperation 完成,避免拖慢主線程潜腻。
SDImageCache 在初始化的時候會注冊一些消息通知强岸,在內(nèi)存警告或退到后臺的時候清理內(nèi)存圖片緩存,應用結(jié)束的時候清理過期圖片砾赔。
SDWI 也提供了 UIButton+WebCache 和 MKAnnotationView+WebCache蝌箍,方便使用。
SDWebImagePrefetcher 可以預先下載圖片暴心,方便后續(xù)使用妓盲。
從上面流程可以看出,當你調(diào)用setImageWithURL:方法的時候专普,他會自動去給你干這么多事悯衬,當你需要在某一具體時刻做事情的時候,你可以覆蓋這些方法檀夹。比如在下載某個圖片的過程中要響應一個事件筋粗,就覆蓋這個方法:
1
2
3
4
5
6
7
8
9
10
11
//覆蓋方法,指哪打哪炸渡,這個方法是下載imagePath2的時候響應
SDWebImageManager manager = [SDWebImageManager sharedManager]; [manager downloadImageWithURL:imagePath2 options:SDWebImageRetryFailed progress:^(NSIntegerreceivedSize,NSIntegerexpectedSize) {NSLog(@"顯示當前進度"); } completed:^(UIImageimage,NSErrorerror, SDImageCacheType cacheType,BOOLfinished,NSURLimageURL) {NSLog(@"下載完成");}];
對于初級來說娜亿,用sd_setImageWithURL:的若干個方法就可以實現(xiàn)很好的圖片緩存。
UIButton 的父類是UIControl UIControl的父類是UIView UIView的父類是 UIResponder
http狀態(tài)嗎 :302 是請求重定向蚌堵。500以上是服務器錯誤买决。400以上是請求鏈接錯誤或者找不到服務器沛婴。200以上是正確。100以上是請求接受成功督赤。
HTTP Keep-Alive詳解[轉(zhuǎn)]
HTTP是一個請求<->響應模式的典型范例嘁灯,即客戶端向服務器發(fā)送一個請求信息,服務器來響應這個信息躲舌。在老的HTTP版本中丑婿,每個請求都將被創(chuàng)建一個新的客戶端->服務器的連接,在這個連接上發(fā)送請求没卸,然后接收請求羹奉。這樣的模式有一個很大的優(yōu)點就是,它很簡單办悟,很容易理解和編程實現(xiàn)尘奏;它也有一個很大的缺點就是,它效率很低病蛉,因此Keep-Alive被提出用來解決效率低的問題炫加。
Keep-Alive功能使客戶端到服務器端的連接持續(xù)有效,當出現(xiàn)對服務器的后繼請求時铺然,Keep-Alive功能避免了建立或者重新建立連接俗孝。市場上 的大部分Web服務器,包括iPlanet魄健、IIS和Apache赋铝,都支持HTTP Keep-Alive。對于提供靜態(tài)內(nèi)容的網(wǎng)站來說沽瘦,這個功能通常很有用革骨。但是,對于負擔較重的網(wǎng)站來說析恋,這里存在另外一個問題:雖然為客戶保留打開的連 接有一定的好處良哲,但它同樣影響了性能,因為在處理暫停期間助隧,本來可以釋放的資源仍舊被占用筑凫。當Web服務器和應用服務器在同一臺機器上運行時,Keep- Alive功能對資源利用的影響尤其突出并村。 此功能為HTTP 1.1預設(shè)的功能巍实,HTTP 1.0加上Keep-Aliveheader也可以提供HTTP的持續(xù)作用功能。
Keep-Alive: timeout=5, max=100
timeout:過期時間5秒(對應httpd.conf里的參數(shù)是:KeepAliveTimeout)哩牍,max是最多一百次請求棚潦,強制斷掉連接
就是在timeout時間內(nèi)又有新的連接過來,同時max會自動減1姐叁,直到為0瓦盛,強制斷掉洗显。見下面的四個圖外潜,注意看Date的值(前后時間差都是在5秒之內(nèi))原环!
HTTP/1.0
在HTTP/1.0版本中,并沒有官方的標準來規(guī)定Keep-Alive如何工作处窥,因此實際上它是被附加到HTTP/1.0協(xié)議上嘱吗,如果客戶端瀏覽器支持Keep-Alive,那么就在HTTP請求頭中添加一個字段 Connection: Keep-Alive滔驾,當服務器收到附帶有Connection: Keep-Alive的請求時谒麦,它也會在響應頭中添加一個同樣的字段來使用Keep-Alive。這樣一來哆致,客戶端和服務器之間的HTTP連接就會被保持绕德,不會斷開(超過Keep-Alive規(guī)定的時間,意外斷電等情況除外)摊阀,當客戶端發(fā)送另外一個請求時耻蛇,就使用這條已經(jīng)建立的連接
HTTP/1.1
在HTTP/1.1版本中,官方規(guī)定的Keep-Alive使用標準和在HTTP/1.0版本中有些不同胞此,默認情況下所在HTTP1.1中所有連接都被保持臣咖,除非在請求頭或響應頭中指明要關(guān)閉:Connection: Close ,這也就是為什么Connection: Keep-Alive字段再沒有意義的原因漱牵。另外夺蛇,還添加了一個新的字段Keep-Alive:,因為這個字段并沒有詳細描述用來做什么酣胀,可忽略它
Not reliable(不可靠)
HTTP是一個無狀態(tài)協(xié)議声功,這意味著每個請求都是獨立的,Keep-Alive沒能改變這個結(jié)果鹦赎。另外讼载,Keep-Alive也不能保證客戶端和服務器之間的連接一定是活躍的,在HTTP1.1版本中也如此儒溉。唯一能保證的就是當連接被關(guān)閉時你能得到一個通知宦焦,所以不應該讓程序依賴于Keep-Alive的保持連接特性,否則會有意想不到的后果
Keep-Alive和POST
在HTTP1.1細則中規(guī)定了在一個POST消息體后面不能有任何字符顿涣,還指出了對于某一個特定的瀏覽器可能并不遵循這個標準(比如在POST消息體的后面放置一個CRLF符)波闹。而據(jù)我所知,大部分瀏覽器在POST消息體后都會自動跟一個CRLF符再發(fā)送涛碑,如何解決這個問題呢精堕?根據(jù)上面的說明在POST請求頭中禁止使用Keep-Alive,或者由服務器自動忽略這個CRLF蒲障,大部分服務器都會自動忽略歹篓,但是在未經(jīng)測試之前是不可能知道一個服務器是否會這樣做瘫证。
1、常用的方法dispatch_async
為了避免界面在處理耗時的操作時卡死庄撮,比如讀取網(wǎng)絡數(shù)據(jù)背捌,IO,數(shù)據(jù)庫讀寫等,我們會在另外一個線程中處理這些操作洞斯,然后通知主線程更新界面毡庆。
用GCD實現(xiàn)這個流程的操作比前面介紹的NSThread NSOperation的方法都要簡單。代碼框架結(jié)構(gòu)如下:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 耗時的操作
dispatch_async(dispatch_get_main_queue(), ^{
// 更新界面
});
});
如果這樣還不清晰的話烙如,那我們還是用上兩篇博客中的下載圖片為例子么抗,代碼如下:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURL * url = [NSURL URLWithString:@"http://avatar.csdn.net/2/C/D/1_totogo2010.jpg"];
NSData * data = [[NSData alloc]initWithContentsOfURL:url];
UIImage *image = [[UIImage alloc]initWithData:data];
if (data != nil) {
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = image;
});
}
});
運行顯示:
是不是代碼比NSThread NSOperation簡潔很多,而且GCD會自動根據(jù)任務在多核處理器上分配資源亚铁,優(yōu)化程序蝇刀。
系統(tǒng)給每一個應用程序提供了三個concurrent dispatch queues。這三個并發(fā)調(diào)度隊列是全局的徘溢,它們只有優(yōu)先級的不同吞琐。因為是全局的,我們不需要去創(chuàng)建甸昏。我們只需要通過使用函數(shù)dispath_get_global_queue去得到隊列顽分,如下:
dispatch_queue_t globalQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
這里也用到了系統(tǒng)默認就有一個串行隊列main_queue
dispatch_queue_t mainQ = dispatch_get_main_queue();
雖然dispatch queue是引用計數(shù)的對象,但是以上兩個都是全局的隊列施蜜,不用retain或release卒蘸。
2、dispatch_group_async的使用
dispatch_group_async可以實現(xiàn)監(jiān)聽一組任務是否完成翻默,完成后得到通知執(zhí)行其他的操作缸沃。這個方法很有用,比如你執(zhí)行三個下載任務修械,當三個任務都下載完成后你才通知界面說完成的了趾牧。下面是一段例子代碼:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"group1");
});
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"group2");
});
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"group3");
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"updateUi");
});
dispatch_release(group);
dispatch_group_async是異步的方法,運行后可以看到打印結(jié)果:
2012-09-25 16:04:16.737 gcdTest[43328:11303] group1
2012-09-25 16:04:17.738 gcdTest[43328:12a1b] group2
2012-09-25 16:04:18.738 gcdTest[43328:13003] group3
2012-09-25 16:04:18.739 gcdTest[43328:f803] updateUi
每個一秒打印一個肯污,當?shù)谌齻€任務執(zhí)行后翘单,upadteUi被打印。
3蹦渣、dispatch_barrier_async的使用
dispatch_barrier_async是在前面的任務執(zhí)行結(jié)束后它才執(zhí)行哄芜,而且它后面的任務等它執(zhí)行完成之后才會執(zhí)行
例子代碼如下:
dispatch_queue_t queue = dispatch_queue_create("gcdtest.rongfzh.yc", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"dispatch_async1");
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:4];
NSLog(@"dispatch_async2");
});
dispatch_barrier_async(queue, ^{
NSLog(@"dispatch_barrier_async");
[NSThread sleepForTimeInterval:4];
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"dispatch_async3");
});
打印結(jié)果:
2012-09-25 16:20:33.967 gcdTest[45547:11203] dispatch_async1
2012-09-25 16:20:35.967 gcdTest[45547:11303] dispatch_async2
2012-09-25 16:20:35.967 gcdTest[45547:11303] dispatch_barrier_async
2012-09-25 16:20:40.970 gcdTest[45547:11303] dispatch_async3
請注意執(zhí)行的時間,可以看到執(zhí)行的順序如上所述柬唯。
4认臊、dispatch_apply
執(zhí)行某個代碼片段N次。
dispatch_apply(5, globalQ, ^(size_t index) {
// 執(zhí)行5次
});
copy與retain:
1锄奢、copy其實是建立了一個相同的對象失晴,而retain不是剧腻;
2、copy是內(nèi)容拷貝涂屁,retain是指針拷貝书在;
3、copy是內(nèi)容的拷貝 ,對于像NSString,的確是這樣胯陋,但是如果copy的是一個NSArray呢?這時只是copy了指向array中相對應元素的指針.這便是所謂的"淺復制".
4蕊温、copy的情況:NSString *newPt = [pt copy];
此時會在堆上重新開辟一段內(nèi)存存放@"abc" 比如0X1122 內(nèi)容為@"abc 同時會在棧上為newPt分配空間 比如地址:0Xaacc 內(nèi)容為0X1122 因此retainCount增加1供newPt來管理0X1122這段內(nèi)存袱箱;
assign與retain:
1遏乔、assign: 簡單賦值,不更改索引計數(shù)发笔;
2盟萨、assign的情況:NSString *newPt = [pt assing];
此時newPt和pt完全相同 地址都是0Xaaaa 內(nèi)容為0X1111 即newPt只是pt的別名,對任何一個操作就等于對另一個操作了讨, 因此retainCount不需要增加捻激;
3、assign就是直接賦值前计;
4胞谭、retain使用了引用計數(shù),retain引起引用計數(shù)加1, release引起引用計數(shù)減1男杈,當引用計數(shù)為0時丈屹,dealloc函數(shù)被調(diào)用,內(nèi)存被回收伶棒;
5旺垒、retain的情況:NSString *newPt = [pt retain];
此時newPt的地址不再為0Xaaaa,可能為0Xaabb 但是內(nèi)容依然為0X1111肤无。 因此newPt 和 pt 都可以管理"abc"所在的內(nèi)存先蒋,因此 retainCount需要增加1 ;
readonly:
1宛渐、屬性是只讀的竞漾,默認的標記是讀寫,如果你指定了只讀窥翩,在@implementation中只需要一個讀取器业岁。或者如果你使用@synthesize關(guān)鍵字鳍烁,也是有讀取器方法被解析
readwrite:
1叨襟、說明屬性會被當成讀寫的,這也是默認屬性幔荒。設(shè)置器和讀取器都需要在@implementation中實現(xiàn)糊闽。如果使用@synthesize關(guān)鍵字梳玫,讀取器和設(shè)置器都會被解析;
nonatomic:
1右犹、非原子性訪問提澎,對屬性賦值的時候不加鎖,多線程并發(fā)訪問會提高性能念链。如果不加此屬性盼忌,則默認是兩個訪問方法都為原子型事務訪問;
weak and strong property (強引用和弱引用的區(qū)別):
1掂墓、 weak 和 strong 屬性只有在你打開ARC時才會被要求使用谦纱,這時你是不能使用retain release autorelease 操作的,因為ARC會自動為你做好這些操作君编,但是你需要在對象屬性上使用weak 和strong,其中strong就相當于retain屬性跨嘉,而weak相當于assign。
2吃嘿、只有一種情況你需要使用weak(默認是strong)祠乃,就是為了避免retain cycles(就是父類中含有子類{父類retain了子類},子類中又調(diào)用了父類{子類又retain了父類}兑燥,這樣都無法release)
3亮瓷、聲明為weak的指針,指針指向的地址一旦被釋放降瞳,這些指針都將被賦值為nil嘱支。這樣的好處能有效的防止野指針。
ARC(Automatic Reference Counting):
1力崇、就是代碼中自動加入了retain/release斗塘,原先需要手動添加的用來處理內(nèi)存管理的引用計數(shù)的代碼可以自動地由編譯器完成了。
該機能在 iOS 5/ Mac OS X 10.7 開始導入亮靴,利用 Xcode4.2 以后可以使用該特性馍盟。
strong,weak,copy 具體用法:
1.具體一點:IBOutlet可以為weak,NSString為copy茧吊,Delegate一般為weak贞岭,其他的看情況。一般來說搓侄,類“內(nèi)部”的屬性設(shè)置為strong瞄桨,類“外部”的屬性設(shè)置為weak。說到底就是一個歸屬權(quán)的問題讶踪。小心出現(xiàn)循環(huán)引用導致內(nèi)存無法釋放芯侥。
2.不用ARC的話就會看到很多retian。
3.如果你寫了@synthesize abc = _abc;的話柱查,系統(tǒng)自動幫你聲明了一個_abc的實例變量廓俭。
使用assign: 對基礎(chǔ)數(shù)據(jù)類型 (NSInteger)和C數(shù)據(jù)類型(int, float, double, char,等)
使用copy: 對NSString
使用retain: 對其他NSObject和其子類
1.寫一個NSString類的實現(xiàn)
(id)initWithCString:(c*****t char *)nullTerminatedCString encoding:(NSStringEncoding)encoding;
(id) stringWithCString: (c*****t char*)nullTerminatedCString
encoding: (NSStringEncoding)encoding
{
NSString *obj;
obj = [self allocWithZone: NSDefaultMallocZone()];
obj = [obj initWithCString: nullTerminatedCString encoding: encoding];
return AUTORELEASE(obj);
}
2static 關(guān)鍵字的作用:
(1)函數(shù)體內(nèi) static 變量的作用范圍為該函數(shù)體,不同于 auto 變量唉工,該變量的內(nèi)存只被分配一次研乒,
因此其值在下次調(diào)用時仍維持上次的值;
(2)在模塊內(nèi)的 static 全局變量可以被模塊內(nèi)所用函數(shù)訪問淋硝,但不能被模塊外其它函數(shù)訪問雹熬;
(3)在模塊內(nèi)的 static 函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用,這個函數(shù)的使用范圍被限制在聲明
它的模塊內(nèi)谣膳;
(4)在類中的 static 成員變量屬于整個類所擁有竿报,對類的所有對象只有一份拷貝;
(5)在類中的 static 成員函數(shù)屬于整個類所擁有参歹,這個函數(shù)不接收 this 指針仰楚,因而只能訪問類的static 成員變量。
3線程與進程的區(qū)別和聯(lián)系?
進程和線程都是由操作系統(tǒng)所體會的程序運行的基本單元犬庇,系統(tǒng)利用該基本單元實現(xiàn)系統(tǒng)對應用的并發(fā)性。
程和線程的主要差別在于它們是不同的操作系統(tǒng)資源管理方式侨嘀。進程有獨立的地址空間臭挽,一個進程崩潰后,在保護模式下不會對其它進程產(chǎn)生影響咬腕,而線程只是一個進程中的不同執(zhí)行路徑欢峰。線程有自己的堆棧和局部變量,但線程之間沒有單獨的地址空間涨共,一個線程死掉就等于整個進程死掉纽帖,所以多進程的程序要比多線程的程序健壯,但在進程切換時举反,耗費資源較大懊直,效率要差一些。但對于一些要求同時進行并且又要共享某些變量的并發(fā)操作火鼻,只能用線程室囊,不能用進程。
4堆和棧的區(qū)別
管理方式:對于棧來講魁索,是由編譯器自動管理融撞,無需我們手工控制;對于堆來說粗蔚,釋放工作由程序員控制尝偎,容易產(chǎn)生memory leak。
申請大信艨亍:
棧:在Windows下,棧是向低地址擴展的數(shù)據(jù)結(jié)構(gòu)致扯,是一塊連續(xù)的內(nèi)存的區(qū)域趁窃。這句話的意思是棧頂?shù)牡刂泛蜅5淖畲笕萘渴窍到y(tǒng)預先規(guī)定好的,在 WINDOWS下急前,棧的大小是2M(也有的說是1M醒陆,總之是一個編譯時就確定的常數(shù)),如果申請的空間超過棧的剩余空間時裆针,將提示overflow刨摩。因此,能從棧獲得的空間較小世吨。
堆:堆是向高地址擴展的數(shù)據(jù)結(jié)構(gòu)澡刹,是不連續(xù)的內(nèi)存區(qū)域。這是由于系統(tǒng)是用鏈表來存儲的空閑內(nèi)存地址的耘婚,自然是不連續(xù)的罢浇,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限于計算機系統(tǒng)中有效的虛擬內(nèi)存沐祷。由此可見嚷闭,堆獲得的空間比較靈活,也比較大赖临。
碎片問題:對于堆來講胞锰,頻繁的new/delete勢必會造成內(nèi)存空間的不連續(xù),從而造成大量的碎片兢榨,使程序效率降低嗅榕。對于棧來講,則不會存在這個問題吵聪,因為棧是先進后出的隊列凌那,他們是如此的一一對應,以至于永遠都不可能有一個內(nèi)存塊從棧中間彈出
分配方式:堆都是動態(tài)分配的吟逝,沒有靜態(tài)分配的堆帽蝶。棧有2種分配方式:靜態(tài)分配和動態(tài)分配。靜態(tài)分配是編譯器完成的澎办,比如局部變量的分配嘲碱。動態(tài)分配由alloca函數(shù)進行分配,但是棧的動態(tài)分配和堆是不同的局蚀,他的動態(tài)分配是由編譯器進行釋放麦锯,無需我們手工實現(xiàn)。
分配效率:棧是機器系統(tǒng)提供的數(shù)據(jù)結(jié)構(gòu)琅绅,計算機會在底層對棧提供支持:分配專門的寄存器存放棧的地址扶欣,壓棧出棧都有專門的指令執(zhí)行,這就決定了棧的效率比較高。堆則是C/C++函數(shù)庫提供的料祠,它的機制是很復雜的骆捧。
5什么是鍵-值,鍵路徑是什么
模型的性質(zhì)是通過一個簡單的鍵(通常是個字符串)來指定的。視圖和控制器通過鍵來查找相應的屬性值髓绽。在一個給定的實體中敛苇,同一個屬性的所有值具有相同的數(shù)據(jù)類型。鍵-值編碼技術(shù)用于進行這樣的查找—它是一種間接訪問對象屬性的機制顺呕。
鍵路徑是一個由用點作分隔符的鍵組成的字符串枫攀,用于指定一個連接在一起的對象性質(zhì)序列。第一個鍵的
性質(zhì)是由先前的性質(zhì)決定的株茶,接下來每個鍵的值也是相對于其前面的性質(zhì)来涨。鍵路徑使您可以以獨立于模型
實現(xiàn)的方式指定相關(guān)對象的性質(zhì)。通過鍵路徑启盛,您可以指定對象圖中的一個任意深度的路徑蹦掐,使其指向相
關(guān)對象的特定屬性。
6目標-動作機制
目標是動作消息的接收者僵闯。一個控件卧抗,或者更為常見的是它的單元,以插座變量(參見"插座變量"部分)
的形式保有其動作消息的目標棍厂。
動作是控件發(fā)送給目標的消息颗味,或者從目標的角度看,它是目標為了響應動作而實現(xiàn)的方法牺弹。
程序需要某些機制來進行事件和指令的翻譯。這個機制就是目標-動作機制时呀。
7objc的內(nèi)存管理
?? 如果您通過分配和初始化(比如[[MyClass alloc] init])的方式來創(chuàng)建對象张漂,您就擁
有這個對象,需要負責該對象的釋放谨娜。這個規(guī)則在使用NSObject的便利方法new 時也同樣適用航攒。
?? 如果您拷貝一個對象,您也擁有拷貝得到的對象趴梢,需要負責該對象的釋放漠畜。
?? 如果您保持一個對象,您就部分擁有這個對象坞靶,需要在不再使用時釋放該對象憔狞。
反過來,
?? 如果您從其它對象那里接收到一個對象彰阴,則您不擁有該對象瘾敢,也不應該釋放它(這個規(guī)則有少數(shù)
的例外,在參考文檔中有顯式的說明)挖胃。
8 自動釋放池是什么,如何工作
當您向一個對象發(fā)送一個autorelease消息時箱锐,Cocoa就會將該對象的一個引用放入到最新的自動釋放池舍扰。它仍然是個正當?shù)膶ο笙哂虼俗詣俞尫懦囟x的作用域內(nèi)的其它對象可以向它發(fā)送消息饵沧。當程序執(zhí)行到作用域結(jié)束的位置時谒出,自動釋放池就會被釋放娩鹉,池中的所有對象也就被釋放建炫。
ojc-c 是通過一種"referring counting"(引用計數(shù))的方式來管理內(nèi)存的, 對象在開始分配內(nèi)存(alloc)的時候引用計數(shù)為一,以后每當碰到有copy,retain的時候引用計數(shù)都會加一, 每當碰到release和autorelease的時候引用計數(shù)就會減一,如果此對象的計數(shù)變?yōu)榱?, 就會被系統(tǒng)銷毀.
NSAutoreleasePool 就是用來做引用計數(shù)的管理工作的,這個東西一般不用你管的.
autorelease和release沒什么區(qū)別,只是引用計數(shù)減一的時機不同而已,autorelease會在對象的使用真正結(jié)束的時候才做引用計數(shù)減一.
9類工廠方法是什么
類工廠方法的實現(xiàn)是為了向客戶提供方便典蜕,它們將分配和初始化合在一個步驟中断盛,返回被創(chuàng)建的對象,并
進行自動釋放處理嘉裤。這些方法的形式是+ (type)className...(其中 className不包括任何前綴)郑临。
工廠方法可能不僅僅為了方便使用。它們不但可以將分配和初始化合在一起屑宠,還可以為初始化過程提供對
象的分配信息厢洞。
類工廠方法的另一個目的是使類(比如NSWorkspace)提供單件實例。雖然init...方法可以確認一
個類在每次程序運行過程只存在一個實例典奉,但它需要首先分配一個“生的”實例躺翻,然后還必須釋放該實例。
工廠方法則可以避免為可能沒有用的對象盲目分配內(nèi)存卫玖。
10單件實例是什么
Foundation 和 Application Kit 框架中的一些類只允許創(chuàng)建單件對象公你,即這些類在當前進程中的唯一實例。舉例來說假瞬,NSFileManager 和NSWorkspace 類在使用時都是基于進程進行單件對象的實例化陕靠。當向這些類請求實例的時候,它們會向您傳遞單一實例的一個引用脱茉,如果該實例還不存在剪芥,則首先進行實例的分配和初始化。單件對象充當控制中心的角色琴许,負責指引或協(xié)調(diào)類的各種服務税肪。如果類在概念上只有一個實例(比如
NSWorkspace),就應該產(chǎn)生一個單件實例榜田,而不是多個實例益兄;如果將來某一天可能有多個實例,您可
以使用單件實例機制箭券,而不是工廠方法或函數(shù)净捅。
11動態(tài)綁定
—在運行時確定要調(diào)用的方法
動態(tài)綁定將調(diào)用方法的確定也推遲到運行時。在編譯時邦鲫,方法的調(diào)用并不和代碼綁定在一起灸叼,只有在消實發(fā)送出來之后神汹,才確定被調(diào)用的代碼。通過動態(tài)類型和動態(tài)綁定技術(shù)古今,您的代碼每次執(zhí)行都可以得到不同的結(jié)果屁魏。運行時因子負責確定消息的接收者和被調(diào)用的方法。運行時的消息分發(fā)機制為動態(tài)綁定提供支持捉腥。當您向一個動態(tài)類型確定了的對象發(fā)送消息時氓拼,運行環(huán)境系統(tǒng)會通過接收者的isa指針定位對象的類,并以此為起點確定被調(diào)用的方法抵碟,方法和消息是動態(tài)綁定的桃漾。而且,您不必在Objective-C 代碼中做任何工作拟逮,就可以自動獲取動態(tài)綁定的好處撬统。您在每次發(fā)送消息時,
特別是當消息的接收者是動態(tài)類型已經(jīng)確定的對象時敦迄,動態(tài)綁定就會例行而透明地發(fā)生恋追。
12obj-c的優(yōu)缺點
objc優(yōu)點:
Cateogies
Posing
動態(tài)識別
指標計算
5)彈性訊息傳遞
不是一個過度復雜的 C 衍生語言
Objective-C 與 C++ 可混合編程
缺點:
不支援命名空間
不支持運算符重載
3)不支持多重繼承
4)使用動態(tài)運行時類型,所有的方法都是函數(shù)調(diào)用罚屋,所以很多編譯時優(yōu)化方法都用不到苦囱。(如內(nèi)聯(lián)函數(shù)等),性能低劣脾猛。
13sprintf,strcpy,memcpy使用上有什么要注意的地方
strcpy是一個字符串拷貝的函數(shù)撕彤,它的函數(shù)原型為strcpy(char *dst, c*****t char *src);
將 src開始的一段字符串拷貝到dst開始的內(nèi)存中去,結(jié)束的標志符號為'\0'猛拴,由于拷貝的長度不是由我們自己控制的羹铅,所以這個字符串拷貝很容易出錯。具備字符串拷貝功能的函數(shù)有memcpy愉昆,這是一個內(nèi)存拷貝函數(shù)睦裳,它的函數(shù)原型為memcpy(chardst, c*****t charsrc, unsigned int len);
將長度為len的一段內(nèi)存,從src拷貝到dst中去撼唾,這個函數(shù)的長度可控。但是會有內(nèi)存疊加的問題哥蔚。
sprintf是格式化函數(shù)倒谷。將一段數(shù)據(jù)通過特定的格式,格式化到一個字符串緩沖區(qū)中去糙箍。sprintf格式化的函數(shù)的長度不可控渤愁,有可能格式化后的字符串會超出緩沖區(qū)的大小,造成溢出深夯。
14答案是:
a) int a; // An integer
b) int *a; // A pointer to an integer
c) inta; // A pointer to a pointer to an integer
d) int a[10]; // An array of 10 integers
e) int a[10]; // An array of 10 pointers to integers
f) int (a)[10]; // A pointer to an array of 10 integers
g) int (a)(int); // A pointer to a function a that takes an integer argument and returns an integer
h) int (
a[10])(int); // An array of 10 pointers to functi***** that take an integer argument and return an integer
15.readwrite抖格,readonly诺苹,assign,retain雹拄,copy收奔,nonatomic屬性的作用
@property是一個屬性訪問聲明,擴號內(nèi)支持以下幾個屬性:
1滓玖,getter=getterName坪哄,setter=setterName,設(shè)置setter與getter的方法名
2势篡,readwrite,readonly翩肌,設(shè)置可供訪問級別
2,assign禁悠,setter方法直接賦值念祭,不進行任何retain操作,為了解決原類型與環(huán)循引用問題
3碍侦,retain粱坤,setter方法對參數(shù)進行release舊值再retain新值,所有實現(xiàn)都是這個順序(CC上有相關(guān)資料)
4祝钢,copy比规,setter方法進行Copy操作,與retain處理流程一樣拦英,先舊值release蜒什,再Copy出新的對象,retainCount為1疤估。這是為了減少對上下文的依賴而引入的機制。
copy是在你不希望a和b共享一塊內(nèi)存時會使用到铃拇。a和b各自有自己的內(nèi)存钞瀑。
5,nonatomic慷荔,非原子性訪問雕什,不加同步,多線程并發(fā)訪問會提高性能显晶。注意贷岸,如果不加此屬性,則默認是兩個訪問方法都為原子型事務訪問磷雇。鎖被加到所屬對象實例級(我是這么理解的...)偿警。
atomic和nonatomic用來決定編譯器生成的getter和setter是否為原子操作。在多線程環(huán)境下唯笙,原子操作是必要的螟蒸,否則有可能引起錯 誤的結(jié)果盒使。加了atomic,setter函數(shù)會變成下面這樣:
16什么時候用delegate七嫌,什么時候用Notification少办?答:delegate針對one-to-one關(guān)系,并且reciever可以返回值 給sender抄瑟,notification 可以針對one-to-one/many/none,reciever無法返回值給sender.所以凡泣,delegate用于sender希望接受到 reciever的某個功能反饋值,notification用于通知多個object某個事件皮假。
17什么是KVC和KVO鞋拟?答:KVC(Key-Value-Coding)內(nèi)部的實現(xiàn):一個對象在調(diào)用setValue的時候,(1)首先根據(jù)方法名找到運行方法的時候所需要的環(huán)境參數(shù)惹资。(2)他會從自己isa指針結(jié)合環(huán)境參數(shù)贺纲,找到具體的方法實現(xiàn)的接口。(3)再直接查找得來的具體的方法實現(xiàn)褪测。KVO(Key-Value- Observing):當觀察者為一個對象的屬性進行了注冊猴誊,被觀察對象的isa指針被修改的時候,isa指針就會指向一個中間類侮措,而不是真實的類懈叹。所以 isa指針其實不需要指向?qū)嵗龑ο笳鎸嵉念悺K晕覀兊某绦蜃詈貌灰蕾囉趇sa指針分扎。在調(diào)用類的方法的時候澄成,最好要明確對象實例的類名
18ViewController 的 loadView, viewDidLoad, viewDidUnload 分別是在什么時候調(diào)用的?在自定義ViewController的時候這幾個函數(shù)里面應該做什么工作畏吓?答:viewDidLoad在view 從nib文件初始化時調(diào)用墨状,loadView在controller的view為nil時調(diào)用。此方法在編程實現(xiàn)view時調(diào)用,view 控制器默認會注冊memory warning notification,當view controller的任何view 沒有用的時候菲饼,viewDidUnload會被調(diào)用肾砂,在這里實現(xiàn)將retain 的view release,如果是retain的IBOutlet view 屬性則不要在這里release,IBOutlet會負責release 。
19
"NSMutableString *"這個數(shù)據(jù)類型則是代表"NSMutableString"對象本身宏悦,這兩者是有區(qū)別的镐确。
而NSString只是對象的指針而已。
面向過程就是分析出解決問題所需要的步驟饼煞,然后用函數(shù)把這些步驟一步一步實現(xiàn)辫塌,使用的時候一個一個依次調(diào)用就可以了。
面向?qū)ο笫前褬?gòu)成問題事務分解成各個對象派哲,建立對象的目的不是為了完成一個步驟,而是為了描敘某個事物在整個解決問題的步驟中的行為掺喻。芭届;
20類別的作用
類別主要有3個作用:
(1)將類的實現(xiàn)分散到多個不同文件或多個不同框架中储矩。
(2)創(chuàng)建對私有方法的前向引用。
(3)向?qū)ο筇砑臃钦絽f(xié)議褂乍。
類別的局限性
有兩方面局限性:
(1)無法向類中添加新的實例變量持隧,類別沒有位置容納實例變量。
(2)名稱沖突逃片,即當類別中的方法與原始類方法名稱沖突時屡拨,類別具有更高的優(yōu)先級。類別方法將完全取代初始方法從而無法再使用初始方法褥实。
無法添加實例變量的局限可以使用字典對象解決
21關(guān)鍵字volatile有什么含意?并給出三個不同的例子:
一個定義為volatile的變量是說這變量可能會被意想不到地改變呀狼,這樣,編譯器就不會去假設(shè)這個變量的值了损离。精確地說就是哥艇,優(yōu)化器在用到
這個變量時必須每次都小心地重新讀取這個變量的值,而不是使用保存在寄存器里的備份僻澎。下面是volatile變量的幾個例子:
? 并行設(shè)備的硬件寄存器(如:狀態(tài)寄存器)
? 一個中斷服務子程序中會訪問到的非自動變量(Non-automatic variables)
? 多線程應用中被幾個任務共享的變量
? 一個參數(shù)既可以是const還可以是volatile嗎貌踏?解釋為什么。
? 一個指針可以是volatile 嗎窟勃?解釋為什么祖乳。
下面是答案:
? 是的。一個例子是只讀的狀態(tài)寄存器秉氧。它是volatile因為它可能被意想不到地改變眷昆。它是const因為程序不應該試圖去修改它。
? 是的谬运。盡管這并不很常見隙赁。一個例子是當一個中服務子程序修該一個指向一個buffer的指針時。
22@synthesize 是系統(tǒng)自動生成getter和setter屬性聲明
@dynamic 是開發(fā)者自已提供相應的屬性聲明
@dynamic 意思是由開發(fā)人員提供相應的代碼:對于只讀屬性需要提供 setter梆暖,對于讀寫屬性需要提供 setter 和 getter伞访。@synthesize 意思是,除非開發(fā)人員已經(jīng)做了轰驳,否則由編譯器生成相應的代碼厚掷,以滿足屬性聲明。
查閱了一些資料確定@dynamic的意思是告訴編譯器,屬性的獲取與賦值方法由用戶自己實現(xiàn), 不自動生成级解。
23Difference between shallow copy and deep copy?
淺復制和深復制的區(qū)別冒黑?
答案:淺層復制:只復制指向?qū)ο蟮闹羔槪粡椭埔脤ο蟊旧怼?/p>
深層復制:復制引用對象本身勤哗。
意思就是說我有個A對象抡爹,復制一份后得到A_copy對象后,對于淺復制來說芒划,A和A_copy指向的是同一個內(nèi)存資源冬竟,復制的只不過是是一個指針欧穴,對象本身資源
還是只有一份,那如果我們對A_copy執(zhí)行了修改操作,那么發(fā)現(xiàn)A引用的對象同樣被修改泵殴,這其實違背了我們復制拷貝的一個思想涮帘。深復制就好理解了,內(nèi)存中存在了
兩份獨立對象本身。
用網(wǎng)上一哥們通俗的話將就是:
淺復制好比你和你的影子笑诅,你完蛋调缨,你的影子也完蛋
深復制好比你和你的克隆人,你完蛋吆你,你的克隆人還活著弦叶。
24What is advantage of categories? What is difference between implementing a category and inheritance?
類別的作用?繼承和類別在實現(xiàn)中有何區(qū)別早处?
答案:category 可以在不獲悉湾蔓,不改變原來代碼的情況下往里面添加新的方法,只能添加砌梆,不能刪除修改默责。
并且如果類別和原來類中的方法產(chǎn)生名稱沖突,則類別將覆蓋原來的方法咸包,因為類別具有更高的優(yōu)先級桃序。
類別主要有3個作用:
(1)將類的實現(xiàn)分散到多個不同文件或多個不同框架中。
(2)創(chuàng)建對私有方法的前向引用烂瘫。
(3)向?qū)ο筇砑臃钦絽f(xié)議媒熊。
繼承可以增加,修改或者刪除方法坟比,并且可以增加屬性芦鳍。
25.Difference between categories and extensions?
類別和類擴展的區(qū)別。
答案:category和extensions的不同在于 后者可以添加屬性葛账。另外后者添加的方法是必須要實現(xiàn)的柠衅。
extensions可以認為是一個私有的Category。
26.Difference between protocol in objective c and interfaces in java?
oc中的協(xié)議和java中的接口概念有何不同籍琳?
答案:OC中的代理有2層含義菲宴,官方定義為 formal和informal protocol。前者和Java接口一樣趋急。
informal protocol中的方法屬于設(shè)計模式考慮范疇喝峦,不是必須實現(xiàn)的,但是如果有實現(xiàn)呜达,就會改變類的屬性谣蠢。
其實關(guān)于正式協(xié)議,類別和非正式協(xié)議我很早前學習的時候大致看過,也寫在了學習教程里
“非正式協(xié)議概念其實就是類別的另一種表達方式“這里有一些你可能希望實現(xiàn)的方法漩怎,你可以使用他們更好的完成工作”勋颖。
這個意思是,這些是可選的勋锤。比如我門要一個更好的方法,我們就會申明一個這樣的類別去實現(xiàn)侥祭。然后你在后期可以直接使用這些更好的方法叁执。
這么看,總覺得類別這玩意兒有點像協(xié)議的可選協(xié)議矮冬。"
現(xiàn)在來看谈宛,其實protocal已經(jīng)開始對兩者都統(tǒng)一和規(guī)范起來操作,因為資料中說“非正式協(xié)議使用interface修飾“胎署,
現(xiàn)在我們看到協(xié)議中兩個修飾詞:“必須實現(xiàn)(@requied)”和“可選實現(xiàn)(@optional)”吆录。
26What are KVO and KVC?
答案:kvc:鍵 - 值編碼是一種間接訪問對象的屬性使用字符串來標識屬性,而不是通過調(diào)用存取方法琼牧,直接或通過實例變量訪問的機制恢筝。
很多情況下可以簡化程序代碼。apple文檔其實給了一個很好的例子巨坊。
kvo:鍵值觀察機制撬槽,他提供了觀察某一屬性變化的方法,極大的簡化了代碼趾撵。
具體用看到嗯哼用到過的一個地方是對于按鈕點擊變化狀態(tài)的的監(jiān)控侄柔。
比如我自定義的一個button
[cpp]
[self addObserver:self forKeyPath:@"highlighted" options:0 context:nil];
pragma mark KVO
(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"highlighted"] ) {
[self setNeedsDisplay];
}
}
對于系統(tǒng)是根據(jù)keypath去取的到相應的值發(fā)生改變,理論上來說是和kvc機制的道理是一樣的占调。
對于kvc機制如何通過key尋找到value:
“當通過KVC調(diào)用對象時暂题,比如:[self valueForKey:@”someKey”]時,程序會自動試圖通過幾種不同的方式解析這個調(diào)用究珊。首先查找對象是否帶有 someKey 這個方法薪者,如果沒找到,會繼續(xù)查找對象是否帶有someKey這個實例變量(iVar)苦银,如果還沒有找到憎瘸,程序會繼續(xù)試圖調(diào)用 -(id) valueForUndefinedKey:這個方法。如果這個方法還是沒有被實現(xiàn)的話泡垃,程序會拋出一個NSUndefinedKeyException異常錯誤捂掰。
(cocoachina.com注:Key-Value Coding查找方法的時候,不僅僅會查找someKey這個方法想括,還會查找getsomeKey這個方法陷谱,前面加一個get,或者_someKey以及_getsomeKey這幾種形式。同時烟逊,查找實例變量的時候也會不僅僅查找someKey這個變量渣窜,也會查找_someKey這個變量是否存在。)
設(shè)計valueForUndefinedKey:方法的主要目的是當你使用-(id)valueForKey方法從對象中請求值時宪躯,對象能夠在錯誤發(fā)生前乔宿,有最后的機會響應這個請求。這樣做有很多好處访雪,下面的兩個例子說明了這樣做的好處详瑞。“
來至cocoa臣缀,這個說法應該挺有道理坝橡。
因為我們知道button卻是存在一個highlighted實例變量.因此為何上面我們只是add一個相關(guān)的keypath就行了,
27What is purpose of delegates?
代理的作用精置?
答案:代理的目的是改變或傳遞控制鏈计寇。允許一個類在某些特定時刻通知到其他類,而不需要獲取到那些類的指針脂倦》可以減少框架復雜度。
另外一點狼讨,代理可以理解為java中的回調(diào)監(jiān)聽機制的一種類似贝淤。
28What are mutable and immutable types in Objective C?
oc中可修改和不可以修改類型。
答案:可修改不可修改的集合類政供。這個我個人簡單理解就是可動態(tài)添加修改和不可動態(tài)添加修改一樣播聪。
比如NSArray和NSMutableArray。前者在初始化后的內(nèi)存控件就是固定不可變的布隔,后者可以添加等离陶,可以動態(tài)申請新的內(nèi)存空間
29When we call objective c is runtime language what does it mean?
我們說的oc是動態(tài)運行時語言是什么意思?
答案:多態(tài)衅檀。主要是將數(shù)據(jù)類型的確定由編譯時招刨,推遲到了運行時。
這個問題其實淺涉及到兩個概念哀军,運行時和多態(tài)沉眶。
簡單來說,運行時機制使我們直到運行時才去決定一個對象的類別杉适,以及調(diào)用該類別對象指定方法谎倔。
多態(tài):不同對象以自己的方式響應相同的消息的能力叫做多態(tài)。意思就是假設(shè)生物類(life)都用有一個相同的方法-eat;
那人類屬于生物猿推,豬也屬于生物片习,都繼承了life后捌肴,實現(xiàn)各自的eat,但是調(diào)用是我們只需調(diào)用各自的eat方法藕咏。
也就是不同的對象以自己的方式響應了相同的消息(響應了eat這個選擇器)状知。
因此也可以說,運行時機制是多態(tài)的基礎(chǔ)孽查?~~~
30what is difference between NSNotification and protocol?
通知和協(xié)議的不同之處饥悴?
答案:協(xié)議有控制鏈(has-a)的關(guān)系,通知沒有盲再。
首先我一開始也不太明白铺坞,什么叫控制鏈(專業(yè)術(shù)語了~)。但是簡單分析下通知和代理的行為模式洲胖,我們大致可以有自己的理解
簡單來說,通知的話坯沪,它可以一對多绿映,一條消息可以發(fā)送給多個消息接受者。
代理按我們的理解腐晾,到不是直接說不能一對多叉弦,比如我們知道的明星經(jīng)濟代理人,很多時候一個經(jīng)濟人負責好幾個明星的事務藻糖。
只是對于不同明星間淹冰,代理的事物對象都是不一樣的,一一對應巨柒,不可能說明天要處理A明星要一個發(fā)布會樱拴,代理人發(fā)出處理發(fā)布會的消息后,別稱B的
發(fā)布會了洋满。但是通知就不一樣晶乔,他只關(guān)心發(fā)出通知,而不關(guān)心多少接收到感興趣要處理牺勾。
因此控制鏈(has-a從英語單詞大致可以看出正罢,單一擁有和可控制的對應關(guān)系。
31What is push notification?
什么是推送消息驻民?
答案:太簡單翻具,不作答~~~~~~~~~~
這是cocoa上的答案。
其實到不是說太簡單回还,只是太泛泛的一個概念的東西裆泳。就好比說,什么是人懦趋。
推送通知更是一種技術(shù)晾虑。
簡單點就是客戶端獲取資源的一種手段。
普通情況下,都是客戶端主動的pull帜篇。
推送則是服務器端主動push糙捺。
32.Polymorphism?
關(guān)于多態(tài)性
答案:多態(tài)笙隙,子類指針可以賦值給父類洪灯。
這個題目其實可以出到一切面向?qū)ο笳Z言中,
因此關(guān)于多態(tài)竟痰,繼承和封裝基本最好都有個自我意識的理解签钩,也并非一定要把書上資料上寫的能背出來。
最重要的是轉(zhuǎn)化成自我理解坏快。
33
What is responder chain?
說說響應鏈
答案:事件響應鏈铅檩。包括點擊事件,畫面刷新事件等莽鸿。在視圖棧內(nèi)從上至下昧旨,或者從下之上傳播。
可以說點事件的分發(fā)祥得,傳遞以及處理兔沃。具體可以去看下touch事件這塊。因為問的太抽象化了
嚴重懷疑題目出到越后面就越籠統(tǒng)级及。
34Difference between frame and bounds?
frame和bounds有什么不同乒疏?
答案:frame指的是:該view在父view坐標系統(tǒng)中的位置和大小。(參照點是父親的坐標系統(tǒng))
bounds指的是:該view在本身坐標系統(tǒng)中 的位置和大小饮焦。(參照點是本身坐標系統(tǒng))
35
.Difference between method and selector?
方法和選擇器有何不同怕吴?
答案:selector是一個方法的名字,method是一個組合體追驴,包含了名字和實現(xiàn).
36NSOperation queue?
答案:存放NSOperation的集合類械哟。
操作和操作隊列,基本可以看成java中的線程和線程池的概念殿雪。用于處理ios多線程開發(fā)的問題暇咆。
網(wǎng)上部分資料提到一點是,雖然是queue丙曙,但是卻并不是帶有隊列的概念爸业,放入的操作并非是按照嚴格的先進現(xiàn)出。
這邊又有個疑點是亏镰,對于隊列來說扯旷,先進先出的概念是Afunc添加進隊列,Bfunc緊跟著也進入隊列索抓,Afunc先執(zhí)行這個是必然的钧忽,
但是Bfunc是等Afunc完全操作完以后毯炮,B才開始啟動并且執(zhí)行,因此隊列的概念離亂上有點違背了多線程處理這個概念耸黑。
但是轉(zhuǎn)念一想其實可以參考銀行的取票和叫號系統(tǒng)桃煎。
因此對于A比B先排隊取票但是B率先執(zhí)行完操作,我們亦然可以感性認為這還是一個隊列大刊。
但是后來看到一票關(guān)于這操作隊列話題的文章为迈,其中有一句提到
“因為兩個操作提交的時間間隔很近,線程池中的線程缺菌,誰先啟動是不定的葫辐。”
瞬間覺得這個queue名字有點忽悠人了伴郁,還不如pool~
綜合一點耿战,我們知道他可以比較大的用處在于可以幫組多線程編程就好了。
37What is lazy loading?
答案:懶漢模式焊傅,只在用到的時候才去初始化昆箕。
也可以理解成延時加載。
我覺得最好也最簡單的一個列子就是tableView中圖片的加載顯示了租冠。
一個延時載,避免內(nèi)存過高薯嗤,一個異步加載顽爹,避免線程堵塞。
38Can we use two tableview controllers on one viewcontroller?
是否在一個視圖控制器中嵌入兩個tableview控制器骆姐?
答案:一個視圖控制只提供了一個View視圖镜粤,理論上一個tableViewController也不能放吧,
只能說可以嵌入一個tableview視圖玻褪。當然肉渴,題目本身也有歧義,如果不是我們定性思維認為的UIViewController带射,
而是宏觀的表示視圖控制者同规,那我們倒是可以把其看成一個視圖控制者,它可以控制多個視圖控制器窟社,比如TabbarController
那樣的感覺券勺。
39Can we use one tableview with two different datasources? How you will achieve this?
一個tableView是否可以關(guān)聯(lián)兩個不同的數(shù)據(jù)源?你會怎么處理灿里?
答案:首先我們從代碼來看关炼,數(shù)據(jù)源如何關(guān)聯(lián)上的,其實是在數(shù)據(jù)源關(guān)聯(lián)的代理方法里實現(xiàn)的匣吊。
因此我們并不關(guān)心如何去關(guān)聯(lián)他儒拂,他怎么關(guān)聯(lián)上寸潦,方法只是讓我返回根據(jù)自己的需要去設(shè)置如相關(guān)的數(shù)據(jù)源。
因此社痛,我覺得可以設(shè)置多個數(shù)據(jù)源啊见转,但是有個問題是,你這是想干嘛呢褥影?想讓列表如何顯示池户,不同的數(shù)據(jù)源分區(qū)塊顯示?
40id凡怎、nil代表什么校焦?
id和void *并非完全一樣。在上面的代碼中统倒,id是指向struct objc_object的一個指針寨典,這個意思基本上是說,id是一個指向任何一個繼承了Object(或者NSObject)類的對象房匆。需要注意的是id是一個指針耸成,所以你在使用id的時候不需要加星號。比如id foo=nil定義了一個nil指針浴鸿,這個指針指向NSObject的一個任意子類井氢。而id *foo=nil則定義了一個指針,這個指針指向另一個指針岳链,被指向的這個指針指向NSObject的一個子類花竞。
nil和C語言的NULL相同,在objc/objc.h中定義掸哑。nil表示一個Objctive-C對象约急,這個對象的指針指向空(沒有東西就是空)。
首字母大寫的Nil和nil有一點不一樣苗分,Nil定義一個指向空的類(是Class厌蔽,而不是對象)。
SEL是“selector”的一個類型摔癣,表示一個方法的名字
Method(我們常說的方法)表示一種類型奴饮,這種類型與selector和實現(xiàn)(implementation)相關(guān)
IMP定義為 id (*IMP) (id, SEL, …)。這樣說來择浊, IMP是一個指向函數(shù)的指針拐云,這個被指向的函數(shù)包括id(“self”指針),調(diào)用的SEL(方法名)近她,再加上一些其他參數(shù).說白了IMP就是實現(xiàn)方法叉瘩。
41層和UIView的區(qū)別是什么?
答:兩者最大的區(qū)別是,圖層不會直接渲染到屏幕上粘捎,UIView是iOS系統(tǒng)中界面元素的基礎(chǔ)薇缅,所有的界面元素都是繼承自它危彩。它本身完全是由CoreAnimation來實現(xiàn)的。它真正的繪圖部分泳桦,是由一個CALayer類來管理汤徽。UIView本身更像是一個CALayer的管理器。一個UIView上可以有n個CALayer灸撰,每個layer顯示一種東西谒府,增強UIView的展現(xiàn)能力。
42GCD為Grand Central Dispatch的縮寫浮毯⊥暌撸 Grand Central Dispatch (GCD)是Apple開發(fā)的一個多核編程的較新的解決方法。在Mac OS X 10.6雪豹中首次推出债蓝,并在最近引入到了iOS4.0壳鹤。 GCD是一個替代諸如NSThread等技術(shù)的很高效和強大的技術(shù)饰迹。GCD完全可以處理諸如數(shù)據(jù)鎖定和資源泄漏等復雜的異步編程問題芳誓。
GCD可以完成很多事情,但是這里僅關(guān)注在iOS應用中實現(xiàn)多線程所需的一些基礎(chǔ)知識啊鸭∏绿剩 在開始之前,需要理解是要提供給GCD隊列的是代碼塊赠制,用于在系統(tǒng)或者用戶創(chuàng)建的的隊列上調(diào)度運行葛圃。 聲明一個隊列
如下會返回一個用戶創(chuàng)建的隊列:
dispatch_queue_t myQueue = dispatch_queue_create("com.iphonedevblog.post", NULL);其中憎妙,第一個參數(shù)是標識隊列的,第二個參數(shù)是用來定義隊列的參數(shù)(目前不支持曲楚,因此傳入NULL)厘唾。
執(zhí)行一個隊列
如下會異步執(zhí)行傳入的代碼:
dispatch_async(myQueue, ^{ [self doSomething]; });其中,首先傳入之前創(chuàng)建的隊列龙誊,然后提供由隊列運行的代碼塊抚垃。
聲明并執(zhí)行一個隊列
如果不需要保留要運行的隊列的引用,可以通過如下代碼實現(xiàn)之前的功能: dispatch_async(dispatch_queue_create ("com.iphonedevblog.post", NULL), ^{ [self doSomething]; }); 如果需要暫停一個隊列趟大,可以調(diào)用如下代碼鹤树。暫停一個隊列會阻止和該隊列相關(guān)的所有代碼運行⊙沸啵 dispatch_suspend(myQueue);暫停一個隊列
如果暫停一個隊列不要忘記恢復罕伯。暫停和恢復的操作和內(nèi)存管理中的retain和release類似。調(diào)用dispatch_suspend會增加暫停計數(shù)叽讳,而dispatch_resume則會減少追他。隊列只有在暫停計數(shù)變成零的情況下才開始運行坟募。dispatch_resume(myQueue);恢復一個隊列 從隊列中在主線程運行代碼 有些操作無法在異步隊列運行,因此必須在主線程(每個應用都有一個)上運行邑狸。UI繪圖以及任何對NSNotificationCenter的調(diào)用必須在主線程長進行懈糯。在另一個隊列中訪問主線程并運行代碼的示例如下: dispatch_sync(dispatch_get_main_queue(), ^{ [self dismissLoginWindow]; });注意,dispatch_suspend (以及dispatch_resume)在主線程上不起作用单雾。
使用GCD赚哗,可以讓你的程序不會失去響應. 多線程不容易使用,用了GCD硅堆,會讓它變得簡單屿储。你無需專門進行線程管理, 很棒!
dispatch_queue_t t1=dispatch_queue_create("1", NULL);
dispatch_queue_t t2=dispatch_queue_create("2", NULL);
dispatch_async(t1, ^{
[self print1];
});
dispatch_async(t2, ^{
[self print2];
});
43Provider是指某個iPhone軟件的Push服務器硬萍,這篇文章我將使用.net作為Provider扩所。
APNS 是Apple Push Notification Service(Apple Push服務器)的縮寫,是蘋果的服務器朴乖。
上圖可以分為三個階段祖屏。
第一階段:.net應用程序把要發(fā)送的消息、目的iPhone的標識打包买羞,發(fā)給APNS袁勺。
第二階段:APNS在自身的已注冊Push服務的iPhone列表中,查找有相應標識的iPhone畜普,并把消息發(fā)到iPhone期丰。
第三階段:iPhone把發(fā)來的消息傳遞給相應的應用程序,并且按照設(shè)定彈出Push通知吃挑。
http://blog.csdn.net/zhuqilin0/article/details/6527113//消息推送機制
看內(nèi)存泄露時候:在搜索中搜索run 找到Run Static Snalyzer .
44.可擴展標記語言extensible markup language;XML
2.用于標記電子文件使其具有結(jié)構(gòu)性的標記語言钝荡,可以用來標記數(shù)據(jù)、定義數(shù)據(jù)類型舶衬,是一種允許用戶對自己的標記語言進行定義的源語言埠通。
3,數(shù)據(jù)庫提供了更強有力的數(shù)據(jù)存儲和分析能力逛犹,例如:數(shù)據(jù)索引端辱、排序、查找虽画、相關(guān)一致性等舞蔽,XML僅僅是存儲數(shù)據(jù)。
4.XML與HTML的設(shè)計區(qū)別是:XML的核心是數(shù)據(jù)码撰,其重點是數(shù)據(jù)的內(nèi)容渗柿。而HTML 被設(shè)計用來顯示數(shù)據(jù),其重點是數(shù)據(jù)的顯示脖岛。
5.XML和HTML語法區(qū)別:HTML的標記不是所有的都需要成對出現(xiàn),XML則要求所有的標記必須成對出現(xiàn);HTML標記不區(qū)分大小寫漾狼,XML則大小敏感,即區(qū)分大小寫咨堤。
結(jié)合
XML的簡單使其易于在任何應用程序中讀寫數(shù)據(jù),這使XML很快成為數(shù)據(jù)交換的唯一公共語言,雖然不同的應用軟件也支持其它的數(shù)據(jù)交換格式,但不久之后他們都將支持XML,那就意味著程序可以更容易的與Windows,Mac OS,Linux以及其他平臺下產(chǎn)生的信息結(jié)合狠鸳,然后可以很容易加載XML數(shù)據(jù)到程序中并分析他,并以XML格式輸出結(jié)果悯嗓。
XML去掉了之前令許多開發(fā)人員頭疼的SGML(標準通用標記語言)的隨意語法件舵。在XML中,采用了如下的語法:
1 任何的起始標簽都必須有一個結(jié)束標簽脯厨。
2 可以采用另一種簡化語法铅祸,可以在一個標簽中同時表示起始和結(jié)束標簽。這種語法是在大于符號之前緊跟一個斜線(/)合武,例如临梗。XML解析器會將其翻譯成。
3 標簽必須按合適的順序進行嵌套稼跳,所以結(jié)束標簽必須按鏡像順序匹配起始標簽盟庞,例如this is a samplestring。這好比是將起始和結(jié)束標簽看作是數(shù)學中的左右括號:在沒有關(guān)閉所有的內(nèi)部括號之前汤善,是不能關(guān)閉外面的括號的什猖。
4 所有的特性都必須有值。
5 所有的特性都必須在值的周圍加上雙引號红淡。
45union u
{
double a;
int b;
};
union u2
{
char a[13];
int b;
};
union u3
{
char a[13];
char b;
};
cout<
cout<
cout<
都知道union的大小取決于它所有的成員中不狮,占用空間最大的一個成員的大小。所以對于u來說在旱,大小就是最大的double類型成員a了摇零,所以 sizeof(u)=sizeof(double)=8。但是對于u2和u3颈渊,最大的空間都是char[13]類型的數(shù)組,為什么u3的大小是13终佛,而 u2是16呢俊嗽?關(guān)鍵在于u2中的成員int b。由于int類型成員的存在铃彰,使u2的對齊方式變成4绍豁,也就是說,u2的大小必須在4的對界上牙捉,所以占用的空間變成了16(最接近13的對界)竹揍。 struct s1
{
char a;
double b;
int c;
char d;
};
struct s2
{
char a;
char b;
int c;
double d;
};
cout<
cout<
同樣是兩個char類型敬飒,一個int類型,一個double類型芬位,但是因為對界問題无拗,導致他們的大小不同。計算結(jié)構(gòu)體大小可以采用元素擺放法昧碉,我舉例子說明一下:首先英染,CPU判斷結(jié)構(gòu)體的對界,根據(jù)上一節(jié)的結(jié)論被饿,s1和s2的對界都取最大的元素類型四康,也就是double類型的對界8。然后開始擺放每個元素狭握。
對于s1闪金,首先把a放到8的對界,假定是0论颅,此時下一個空閑的地址是1哎垦,但是下一個元素d是double類型,要放到8的對界上嗅辣,離1最接近的地址是8了撼泛,所以d被放在了8,此時下一個空閑地址變成了16澡谭,下一個元素c的對界是4愿题,16可以滿足,所以c放在了16蛙奖,此時下一個空閑地址變成了20潘酗,下一個元素d需要對界1,也正好落在對界上雁仲,所以d放在了20仔夺,結(jié)構(gòu)體在地址21處結(jié)束。由于s1的大小需要是8的倍數(shù)攒砖,所以21- 23的空間被保留缸兔,s1的大小變成了24。
對于s2吹艇,首先把a放到8的對界惰蜜,假定是0,此時下一個空閑地址是1受神,下一個元素的對界也是1抛猖,所以b擺放在1,下一個空閑地址變成了2;下一個元素c的對界是4财著,所以取離2最近的地址4擺放c联四,下一個空閑地址變成了8,下一個元素d的對界是 8撑教,所以d擺放在8朝墩,所有元素擺放完畢,結(jié)構(gòu)體在15處結(jié)束驮履,占用總空間為16鱼辙,正好是8的倍數(shù)。
46ASIDownloadCache 設(shè)置下載緩存
它對Get請求的響應數(shù)據(jù)進行緩存(被緩存的數(shù)據(jù)必需是成功的200請求):
[ASIHTTPRequest setDefaultCache:[ASIDownloadCache sharedCache]];
當設(shè)置緩存策略后玫镐,所有的請求都被自動的緩存起來倒戏。
另外,如果僅僅希望某次請求使用緩存操作恐似,也可以這樣使用:
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
緩存存儲方式
你可以設(shè)置緩存的數(shù)據(jù)需要保存多長時間杜跷,ASIHTTPRequest提供了兩種策略:
a,ASICacheForSessionDurationCacheStoragePolicy矫夷,默認策略葛闷,基于session的緩存數(shù)據(jù)存儲。當下次運行或[ASIHTTPRequest clearSession]時双藕,緩存將失效淑趾。
b,ASICachePermanentlyCacheStoragePolicy忧陪,把緩存數(shù)據(jù)永久保存在本地扣泊,
如:
ASIHTTPRequest *request = [ ASIHTTPRequest requestWithURL:url ];
[ request setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy ];
47HTTP協(xié)議詳解
HTTP是一個屬于應用層的面向?qū)ο蟮膮f(xié)議,由于其簡捷嘶摊、快速的方式延蟹,適用于分布式超媒體信息系統(tǒng)。目前在WWW中使用的是HTTP/1.0的第六版叶堆,HTTP/1.1的規(guī)范化工作正在進行之中阱飘。
http(超文本傳輸協(xié)議)是一個基于請求與響應模式的、無狀態(tài)的虱颗、應用層的協(xié)議沥匈,常基于TCP的連接方式忘渔,HTTP1.1版本中給出一種持續(xù)連接的機制高帖,絕大多數(shù)的Web開發(fā),都是構(gòu)建在HTTP協(xié)議之上的Web應用辨萍。
HTTP協(xié)議的主要特點可概括如下:
1.支持客戶/服務器模式棋恼。
2.簡單快速:客戶向服務器請求服務時,只需傳送請求方法和路徑锈玉。請求方法常用的有GET爪飘、HEAD、POST拉背。每種方法規(guī)定了客戶與服務器聯(lián)系的類型不同师崎。由于HTTP協(xié)議簡單,使得HTTP服務器的程序規(guī)模小椅棺,因而通信速度很快犁罩。
3.靈活:HTTP允許傳輸任意類型的數(shù)據(jù)對象。正在傳輸?shù)念愋陀蒀ontent-Type加以標記两疚。
4.無連接:無連接的含義是限制每次連接只處理一個請求床估。服務器處理完客戶的請求,并收到客戶的應答后诱渤,即斷開連接丐巫。采用這種方式可以節(jié)省傳輸時間。
5.無狀態(tài):HTTP協(xié)議是無狀態(tài)協(xié)議勺美。無狀態(tài)是指協(xié)議對于事務處理沒有記憶能力递胧。缺少狀態(tài)意味著如果后續(xù)處理需要前面的信息,則它必須重傳赡茸,這樣可能導致每次連接傳送的數(shù)據(jù)量增大缎脾。另一方面,在服務器不需要先前信息時它的應答就較快占卧。
48URL
HTTP URL (URL是一種特殊類型的URI是他的子類遗菠,包含了用于查找某個資源的足夠的信息)的格式如下:
[http://host":"port][abs_path]
http表示要通過HTTP協(xié)議來定位網(wǎng)絡資源;host表示合法的Internet主機域名或者IP地址屉栓;port指定一個端口號舷蒲,為空則使用缺省端口80;abs_path指定請求資源的URI友多;如果URL中沒有給出abs_path牲平,那么當它作為請求URI時,必須以“/”的形式給出域滥,通常這個工作瀏覽器自動幫我們完成纵柿。
49TCP/UDP區(qū)別聯(lián)系
TCP---傳輸控制協(xié)議,提供的是面向連接、可靠的字節(jié)流服務启绰。當客戶和服務器彼此交換數(shù)據(jù)前昂儒,必須先在雙方之間建立一個TCP連接,之后才能傳輸數(shù)據(jù)委可。TCP提供超時重發(fā)渊跋,丟棄重復數(shù)據(jù)腊嗡,檢驗數(shù)據(jù),流量控制等功能拾酝,保證數(shù)據(jù)能從一端傳到另一端燕少。
UDP---用戶數(shù)據(jù)報協(xié)議,是一個簡單的面向數(shù)據(jù)報的運輸層協(xié)議蒿囤。UDP不提供可靠性客们,它只是把應用程序傳給IP層的數(shù)據(jù)報發(fā)送出去,但是并不能保證它們能到達目的地材诽。由于UDP在傳輸數(shù)據(jù)報前不用在客戶和服務器之間建立一個連接底挫,且沒有超時重發(fā)等機制,故而傳輸速度很快
TCP(Transmission Control Protocol脸侥,傳輸控制協(xié)議)是基于連接的協(xié)議建邓,也就是說,在正式收發(fā)數(shù)據(jù)前睁枕,必須和對方建立可靠的連接涝缝。一個TCP連接必須要經(jīng)過三次“對話”才能建立起來,我們來看看這三次對話的簡單過程:1.主機A向主機B發(fā)出連接請求數(shù)據(jù)包譬重;2.主機B向主機A發(fā)送同意連接和要求同步(同步就是兩臺主機一個在發(fā)送拒逮,一個在接收,協(xié)調(diào)工作)的數(shù)據(jù)包臀规;3.主機A再發(fā)出一個數(shù)據(jù)包確認主機B的要求同步:“我現(xiàn)在就發(fā)滩援,你接著吧!”塔嬉,這是第三次對話玩徊。三次“對話”的目的是使數(shù)據(jù)包的發(fā)送和接收同步,經(jīng)過三次“對話”之后谨究,主機A才向主機B正式發(fā)送數(shù)據(jù)恩袱。
UDP(User Data Protocol,用戶數(shù)據(jù)報協(xié)議)是與TCP相對應的協(xié)議胶哲。它是面向非連接的協(xié)議畔塔,它不與對方建立連接,而是直接就把數(shù)據(jù)包發(fā)送過去鸯屿! UDP適用于一次只傳送少量數(shù)據(jù)澈吨、對可靠性要求不高的應用環(huán)境。
tcp協(xié)議和udp協(xié)議的差別
是否連接面向連接面向非連接
傳輸可靠性可靠不可靠
應用場合傳輸大量數(shù)據(jù)少量數(shù)據(jù)
速度慢快
50socket連接和http連接的區(qū)別
簡單說寄摆,你瀏覽的網(wǎng)頁(網(wǎng)址以http://開頭)都是http協(xié)議傳輸?shù)侥愕臑g覽器的, 而http是基于socket之上的谅辣。socket是一套完成tcp,udp協(xié)議的接口婶恼。
HTTP協(xié)議:簡單對象訪問協(xié)議桑阶,對應于應用層 柏副,HTTP協(xié)議是基于TCP連接的
tcp協(xié)議: 對應于傳輸層
ip協(xié)議: 對應于網(wǎng)絡層
TCP/IP是傳輸層協(xié)議,主要解決數(shù)據(jù)如何在網(wǎng)絡中傳輸蚣录;而HTTP是應用層協(xié)議搓扯,主要解決如何包裝數(shù)據(jù)。
Socket是對TCP/IP協(xié)議的封裝包归,Socket本身并不是協(xié)議,而是一個調(diào)用接口(API)铅歼,通過Socket公壤,我們才能使用TCP/IP協(xié)議。
http連接:http連接就是所謂的短連接椎椰,即客戶端向服務器端發(fā)送一次請求厦幅,服務器端響應后連接即會斷掉;
socket連接:socket連接就是所謂的長連接慨飘,理論上客戶端和服務器端一旦建立起連接將不會主動斷掉确憨;但是由于各種環(huán)境因素可能會是連接斷開,比如說:服務器端或客戶端主機down了瓤的,網(wǎng)絡故障休弃,或者兩者之間長時間沒有數(shù)據(jù)傳輸,網(wǎng)絡防火墻可能會斷開該連接以釋放網(wǎng)絡資源圈膏。所以當一個socket連接中沒有數(shù)據(jù)的傳輸塔猾,那么為了維持連接需要發(fā)送心跳消息~~具體心跳消息格式是開發(fā)者自己定義的
我們已經(jīng)知道網(wǎng)絡中的進程是通過socket來通信的,那什么是socket呢稽坤?socket起源于Unix丈甸,而Unix/Linux基本哲學之一就是“一切皆文件”,都可以用“打開open –> 讀寫write/read –> 關(guān)閉close”模式來操作尿褪。我的理解就是Socket就是該模式的一個實現(xiàn)睦擂,socket即是一種特殊的文件,一些socket函數(shù)就是對其進行的操作(讀/寫IO杖玲、打開顿仇、關(guān)閉),這些函數(shù)我們在后面進行介紹摆马。我們在傳輸數(shù)據(jù)時夺欲,可以只使用(傳輸層)TCP/IP協(xié)議,但是那樣的話今膊,如果沒有應用層些阅,便無法識別數(shù)據(jù)內(nèi)容,如果想要使傳輸?shù)臄?shù)據(jù)有意義斑唬,則必須使用到應用層協(xié)議市埋,應用層協(xié)議有很多黎泣,比如HTTP、FTP缤谎、TELNET等抒倚,也可以自己定義應用層協(xié)議。WEB使用HTTP協(xié)議作應用層協(xié)議坷澡,以封裝HTTP文本信息托呕,然后使用TCP/IP做傳輸層協(xié)議將它發(fā)到網(wǎng)絡上。
1)Socket是一個針對TCP和UDP編程的接口频敛,你可以借助它建立TCP連接等等项郊。而TCP和UDP協(xié)議屬于傳輸層 。
而http是個應用層的協(xié)議斟赚,它實際上也建立在TCP協(xié)議之上着降。
(HTTP是轎車,提供了封裝或者顯示數(shù)據(jù)的具體形式拗军;Socket是發(fā)動機任洞,提供了網(wǎng)絡通信的能力。)
2)Socket是對TCP/IP協(xié)議的封裝发侵,Socket本身并不是協(xié)議交掏,而是一個調(diào)用接口(API),通過Socket刃鳄,我們才能使用TCP/IP協(xié)議耀销。Socket的出現(xiàn)只是使得程序員更方便地使用TCP/IP協(xié)議棧而已,是對TCP/IP協(xié)議的抽象铲汪,從而形成了我們知道的一些最基本的函數(shù)接口熊尉。
51什么是TCP連接的三次握手
第一次握手:客戶端發(fā)送syn包(syn=j)到服務器,并進入SYN_SEND狀態(tài)掌腰,等待服務器確認狰住;
第二次握手:服務器收到syn包,必須確認客戶的SYN(ack=j+1)齿梁,同時自己也發(fā)送一個SYN包(syn=k)催植,即SYN+ACK包,此時服務器進入SYN_RECV狀態(tài)勺择;
第三次握手:客戶端收到服務器的SYN+ACK包创南,向服務器發(fā)送確認包ACK(ack=k+1),此包發(fā)送完畢省核,客戶端和服務器進入ESTABLISHED狀態(tài)稿辙,完成三次握手。
握手過程中傳送的包里不包含數(shù)據(jù)气忠,三次握手完畢后邻储,客戶端與服務器才正式開始傳送數(shù)據(jù)赋咽。理想狀態(tài)下,TCP連接一旦建立吨娜,在通信雙方中的任何一方主動關(guān)閉連接之前脓匿,TCP 連接都將被一直保持下去。斷開連接時服務器和客戶端均可以主動發(fā)起斷開TCP連接的請求宦赠,斷開過程需要經(jīng)過“四次握手”(過程就不細寫了陪毡,就是服務器和客戶端交互,最終確定斷開)
52利用Socket建立網(wǎng)絡連接的步驟
建立Socket連接至少需要一對套接字勾扭,其中一個運行于客戶端毡琉,稱為ClientSocket ,另一個運行于服務器端尺借,稱為ServerSocket 。
套接字之間的連接過程分為三個步驟:服務器監(jiān)聽精拟,客戶端請求燎斩,連接確認。
1蜂绎。服務器監(jiān)聽:服務器端套接字并不定位具體的客戶端套接字栅表,而是處于等待連接的狀態(tài),實時監(jiān)控網(wǎng)絡狀態(tài)师枣,等待客戶端的連接請求怪瓶。
2〖溃客戶端請求:指客戶端的套接字提出連接請求洗贰,要連接的目標是服務器端的套接字。為此陨倡,客戶端的套接字必須首先描述它要連接的服務器的套接字敛滋,指出服務器端套接字的地址和端口號,然后就向服務器端套接字提出連接請求兴革。
3。連接確認:當服務器端套接字監(jiān)聽到或者說接收到客戶端套接字的連接請求時,就響應客戶端套接字的請求艺晴,建立一個新的線程兽赁,把服務器端套接字的描述發(fā)給客戶端,一旦客戶端確認了此描述擎勘,雙方就正式建立連接咱揍。而服務器端套接字繼續(xù)處于監(jiān)聽狀態(tài),繼續(xù)接收其他客戶端套接字的連接請求棚饵。
53進程與線程
進程(process)是一塊包含了某些資源的內(nèi)存區(qū)域述召。操作系統(tǒng)利用進程把它的工作劃分為一些功能單元朱转。
進程中所包含的一個或多個執(zhí)行單元稱為線程(thread)。進程還擁有一個私有的虛擬地址空間积暖,該空間僅能被它所包含的線程訪問藤为。
通常在一個進程中可以包含若干個線程,它們可以利用進程所擁有的資源夺刑。
在引入線程的操作系統(tǒng)中缅疟,通常都是把進程作為分配資源的基本單位,而把線程作為獨立運行和獨立調(diào)度的基本單位遍愿。
由于線程比進程更小存淫,基本上不擁有系統(tǒng)資源,故對它的調(diào)度所付出的開銷就會小得多沼填,能更高效的提高系統(tǒng)內(nèi)多個程序間并發(fā)執(zhí)行的程度桅咆。
簡而言之,一個程序至少有一個進程,一個進程至少有一個線程.一個程序就是一個進程,而一個程序中的多個任務則被稱為線程坞笙。
線程只能歸屬于一個進程并且它只能訪問該進程所擁有的資源岩饼。當操作系統(tǒng)創(chuàng)建一個進程后,該進程會自動申請一個名為主線程或首要線程的線程薛夜。應用程序(application)是由一個或多個相互協(xié)作的進程組成的籍茧。
另外,進程在執(zhí)行過程中擁有獨立的內(nèi)存單元梯澜,而多個線程共享內(nèi)存寞冯,從而極大地提高了程序的運行效率。
線程在執(zhí)行過程中與進程還是有區(qū)別的晚伙。每個獨立的線程有一個程序運行的入口吮龄、順序執(zhí)行序列和程序的出口。但是線程不能夠獨立執(zhí)行咆疗,必須依存在應用程序中螟蝙,由應用程序提供多個線程執(zhí)行控制。
從邏輯角度來看民傻,多線程的意義在于一個應用程序中胰默,有多個執(zhí)行部分可以同時執(zhí)行。但操作系統(tǒng)并沒有將多個線程看做多個獨立的應用漓踢,來實現(xiàn)進程的調(diào)度和管理以及資源分配牵署。這就是進程和線程的重要區(qū)別。
進程是具有一定獨立功能的程序關(guān)于某個數(shù)據(jù)集合上的一次運行活動,進程是系統(tǒng)進行資源分配和調(diào)度的一個獨立單位.
線程是進程的一個實體,是CPU調(diào)度和分派的基本單位,它是比進程更小的能獨立運行的基本單位.線程自己基本上不擁有系統(tǒng)資源,只擁有一點在運行中必不可少的資源(如程序計數(shù)器,一組寄存器和棧),但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源.
一個線程可以創(chuàng)建和撤銷另一個線程;同一個進程中的多個線程之間可以并發(fā)執(zhí)行.
54多線程
多線程編程是防止主線程堵塞喧半,增加運行效率等等的最佳方法奴迅。而原始的多線程方法存在很多的毛病,包括線程鎖死等。在Cocoa中取具,Apple提供了NSOperation這個類脖隶,提供了一個優(yōu)秀的多線程編程方法。
本次介紹NSOperation的子集暇检,簡易方法的NSInvocationOperation:
一個NSOperationQueue 操作隊列产阱,就相當于一個線程管理器,而非一個線程块仆。因為你可以設(shè)置這個線程管理器內(nèi)可以并行運行的的線程數(shù)量等等
55oc語法里的@perpoerty不用寫@synzhesize了构蹬,自動填充了。并且的_name;
寫方法時候不用提前聲明悔据。llvm 全局方法便利庄敛。
枚舉類型。enum hello:Integer{ } 冒號后面直接可以跟類型科汗,以前是:
enum hello{} 后面在指定為Integer .
橋接藻烤。ARC 自動release retain 的時候 CFString CFArray . Core Fountion. 加上橋接_brige 才能區(qū)分CFString 和NSString 而現(xiàn)在自動區(qū)分了,叫固定橋接头滔。
下拉刷新封裝好了怖亭。
UICollectionViewController. 可以把表格分成多列。
Social Framework(社交集成)
UIActivityViewController來詢問用戶的社交行為
緩存:就是存放在臨時文件里拙毫,比如新浪微博請求的數(shù)據(jù)依许,和圖片棺禾,下次請求看這里有沒有值缀蹄。
56Singleton(單例模式),也叫單子模式膘婶,是一種常用的軟件設(shè)計模式缺前。在應用這個模式時,單例對象的類必須保證只有一個實例存在悬襟。
代碼如下:
static ClassA *classA = nil衅码;//靜態(tài)的該類的實例
(ClassA *)sharedManager
{
@synchronized(self) {
if (!classA) {
classA = [[super allocWithZone:NULL]init];
}
return classA;
}
}
(id)allocWithZone:(NSZone *)zone {
return [[self sharedManager] retain];
}
(id)copyWithZone:(NSZone *)zone {
return self;
}
(id)retain {
return self;
}
(NSUIntger)retainCount {
return NSUIntgerMax;
}
(oneway void)release {
}
(id)autorelease {
return self;
}
-(void)dealloc{
}
57請寫一個C函數(shù),若處理器是Big_endian的脊岳,則返回0逝段;若是Little_endian的,則返回1 int checkCPU( ) {
{
union w
{
int a;
char b;
} c;
c.a = 1;
return (c.b ==1);
}
}
剖析:嵌入式系統(tǒng)開發(fā)者應該對Little-endian和Big-endian模式非常了解割捅。采用Little-endian模式的CPU對操作數(shù)的存放方式是從低字節(jié)到高字節(jié)奶躯, Big-endian 模式的CPU對操作數(shù)的存放方式是從高字節(jié)到低字節(jié)。在弄清楚這個之前要弄清楚這個問題:字節(jié)從右到坐為從高到低! 假設(shè)從地址0x4000開始存放: 0x12345678,是也個32位四個字節(jié)的數(shù)據(jù)亿驾,最高字節(jié)是0x12,最低字節(jié)是0x78:在Little-endian模式CPU內(nèi)存中的存放方式為: (高字節(jié)在高地址, 低字節(jié)在低地址)
內(nèi)存地址0x4000 0x4001 0x4002 0x4003
存放內(nèi)容 0x78 0x56 0x34 0x12
大端機則相反嘹黔。
有的處理器系統(tǒng)采用了小端方式進行數(shù)據(jù)存放,如Intel的奔騰莫瞬。有的處理器系統(tǒng)采用了大端方式進行數(shù)據(jù)存放儡蔓,如IBM半導體和Freescale的PowerPC處理器郭蕉。不僅對于處理器,一些外設(shè)的設(shè)計中也存在著使用大端或者小端進行數(shù)據(jù)存放的選擇喂江。因此在一個處理器系統(tǒng)中召锈,有可能存在大端和小端模式同時存在的現(xiàn)象。這一現(xiàn)象為系統(tǒng)的軟硬件設(shè)計帶來了不小的麻煩开呐,這要求系統(tǒng)設(shè)計工程師烟勋,必須深入理解大端和小端模式的差別。大端與小端模式的差別體現(xiàn)在一個處理器的寄存器筐付,指令集卵惦,系統(tǒng)總線等各個層次中。 聯(lián)合體union的存放順序是所有成員都從低地址開始存放的瓦戚。以上是網(wǎng)上的原文沮尿。讓我們看看在ARM處理器上union是如何存儲的呢? 地址A ---------------- |A |A+1 |A+2 |A+3 |int a; | | | | -------------------- |A |char b; | | --------- 如果是小端如何存儲c.a的呢?
地址A -----------
------------------- |A |A+1 |A+2 |A+3 | int a;
|0x01 |0x00 |0x00 |0x00 | ------------------------------------- |A |char b; | | ---------
如果是大端如何存儲c.a的呢较解?
地址A ---------------------
--------- |A |A+1 |A+2 |A+3 |int a; |0x00 |0x00 |0x00 |0x01 | ------------------------------------------ |A |char b; | | --------- 現(xiàn)在知道為什么c.b==0的話是大端畜疾,c.b==1的話就是小端了吧。
58
堆和棧上的指針
指針所指向的這塊內(nèi)存是在哪里分配的,在堆上稱為堆上的指針,在棧上為棧上的指針.
在堆上的指針,可以保存在全局數(shù)據(jù)結(jié)構(gòu)中,供不同函數(shù)使用訪問同一塊內(nèi)存.
在棧上的指針,在函數(shù)退出后,該內(nèi)存即不可訪問.
59什么是指針的釋放?
具體來說包括兩個概念.
1 釋放該指針指向的內(nèi)存,只有堆上的內(nèi)存才需要我們手工釋放,棧上不需要.
2 將該指針重定向為NULL.
60數(shù)據(jù)結(jié)構(gòu)中的指針?
其實就是指向一塊內(nèi)存的地址,通過指針傳遞,可實現(xiàn)復雜的內(nèi)存訪問.
7 函數(shù)指針?
指向一塊函數(shù)的入口地址.
8 指針作為函數(shù)的參數(shù)?
比如指向一個復雜數(shù)據(jù)結(jié)構(gòu)的指針作為函數(shù)變量
這種方法避免整個復雜數(shù)據(jù)類型內(nèi)存的壓棧出棧操作,提高效率.
注意:指針本身不可變,但指針指向的數(shù)據(jù)結(jié)構(gòu)可以改變.
9 指向指針的指針?
指針指向的變量是一個指針,即具體內(nèi)容為一個指針的值,是一個地址.
此時指針指向的變量長度也是4位.
61指針與地址的區(qū)別?
區(qū)別:
1指針意味著已經(jīng)有一個指針變量存在,他的值是一個地址,指針變量本身也存放在一個長度為四個字節(jié)的地址當中,而地址概念本身并不代表有任何變量存在.
2 指針的值,如果沒有限制,通常是可以變化的,也可以指向另外一個地址.
地址表示內(nèi)存空間的一個位置點,他是用來賦給指針的,地址本身是沒有大小概念,指針指向變量的大小,取決于地址后面存放的變量類型.
62指針與數(shù)組名的關(guān)系?
其值都是一個地址,但前者是可以移動的,后者是不可變的.
12 怎樣防止指針的越界使用問題?
必須讓指針指向一個有效的內(nèi)存地址,
1 防止數(shù)組越界
2 防止向一塊內(nèi)存中拷貝過多的內(nèi)容
3 防止使用空指針
4 防止改變const修改的指針
5 防止改變指向靜態(tài)存儲區(qū)的內(nèi)容
6 防止兩次釋放一個指針
7 防止使用野指針.
13 指針的類型轉(zhuǎn)換?
指針轉(zhuǎn)換通常是指針類型和void * 類型之前進行強制轉(zhuǎn)換,從而與期望或返回void指針的函數(shù)進行正確的交接.
63static有什么用途印衔?(請至少說明兩種)
1.限制變量的作用域
2.設(shè)置變量的存儲域
7. 引用與指針有什么區(qū)別啡捶?
引用必須被初始化,指針不必奸焙。
引用初始化以后不能被改變瞎暑,指針可以改變所指的對象。
不存在指向空值的引用与帆,但是存在指向空值的指針了赌。
8. 描述實時系統(tǒng)的基本特性
在特定時間內(nèi)完成特定的任務,實時性與可靠性
64全局變量和局部變量在內(nèi)存中是否有區(qū)別玄糟?如果有勿她,是什么區(qū)別?
全局變量儲存在靜態(tài)數(shù)據(jù)庫阵翎,局部變量在堆棧
10. 什么是平衡二叉樹逢并?
左右子樹都是平衡二叉樹且左右子樹的深度差值的絕對值不大于1
65堆棧溢出一般是由什么原因?qū)е碌模?/p>
沒有回收垃圾資源
12. 什么函數(shù)不能聲明為虛函數(shù)?
constructor
13. 冒泡排序算法的時間復雜度是什么郭卫?
O(n^2)
14. 寫出float x 與“零值”比較的if語句砍聊。
if(x>0.000001&&x<-0.000001)
16. Internet采用哪種網(wǎng)絡協(xié)議?該協(xié)議的主要層次結(jié)構(gòu)箱沦?
tcp/ip 應用層/傳輸層/網(wǎng)絡層/數(shù)據(jù)鏈路層/物理層
17. Internet物理地址和IP地址轉(zhuǎn)換采用什么協(xié)議辩恼?
ARP (Address Resolution Protocol)(地址解析協(xié)議)
18.IP地址的編碼分為哪倆部分?
IP地址由兩部分組成,網(wǎng)絡號和主機號灶伊。不過是要和“子網(wǎng)掩碼”按位與上之后才能區(qū)
分哪些是網(wǎng)絡位哪些是主機位疆前。
2.用戶輸入M,N值,從1至N開始順序循環(huán)數(shù)數(shù)聘萨,每數(shù)到M輸出該數(shù)值竹椒,直至全部輸出。寫
出C程序米辐。
循環(huán)鏈表胸完,用取余操作做
3.不能做switch()的參數(shù)類型是:
switch的參數(shù)不能為實型。
華為
1翘贮、局部變量能否和全局變量重名赊窥?
答:能,局部會屏蔽全局狸页。要用全局變量锨能,需要使用"::"
局部變量可以與全局變量同名,在函數(shù)內(nèi)引用這個變量時芍耘,會用到同名的局部變量址遇,而
不會用到全局變量。對于有些編譯器而言斋竞,在同一個函數(shù)內(nèi)可以定義多個同名的局部變
量倔约,比如在兩個循環(huán)體內(nèi)都定義一個同名的局部變量,而那個局部變量的作用域就在那
個循環(huán)體內(nèi)
2坝初、如何引用一個已經(jīng)定義過的全局變量浸剩?
答:extern
可以用引用頭文件的方式,也可以用extern關(guān)鍵字脖卖,如果用引用頭文件方式來引用某個
在頭文件中聲明的全局變理乒省,假定你將那個變寫錯了巧颈,那么在編譯期間會報錯畦木,如果你
用extern方式引用時,假定你犯了同樣的錯誤砸泛,那么在編譯期間不會報錯十籍,而在連接期
間報錯
3、全局變量可不可以定義在可被多個.C文件包含的頭文件中唇礁?為什么勾栗?
答:可以,在不同的C文件中以static形式來聲明同名全局變量盏筐。
可以在不同的C文件中聲明同名的全局變量围俘,前提是其中只能有一個C文件中對此變量賦
初值,此時連接不會出錯
4、語句for( 界牡;1 簿寂;)有什么問題?它是什么意思宿亡?
答:和while(1)相同常遂。
5、do……while和while……do有什么區(qū)別挽荠?
答:前一個循環(huán)一遍再判斷克胳,后一個判斷以后再循環(huán)
661.IP Phone的原理是什么?
IPV6
2.TCP/IP通信建立的過程怎樣,端口有什么作用圈匆?
三次握手漠另,確定是哪個應用程序使用該協(xié)議
3.1號信令和7號信令有什么區(qū)別,我國某前廣泛使用的是那一種跃赚?
4.列舉5種以上的電話新業(yè)務酗钞?
微軟亞洲技術(shù)中心的面試題!@蠢邸砚作!
1.進程和線程的差別。
線程是指進程內(nèi)的一個執(zhí)行單元,也是進程內(nèi)的可調(diào)度實體.
與進程的區(qū)別:
(1)調(diào)度:線程作為調(diào)度和分配的基本單位嘹锁,進程作為擁有資源的基本單位
(2)并發(fā)性:不僅進程之間可以并發(fā)執(zhí)行葫录,同一個進程的多個線程之間也可并發(fā)執(zhí)行
(3)擁有資源:進程是擁有資源的一個獨立單位,線程不擁有系統(tǒng)資源领猾,但可以訪問隸屬
于進程的資源.
(4)系統(tǒng)開銷:在創(chuàng)建或撤消進程時米同,由于系統(tǒng)都要為之分配和回收資源,導致系統(tǒng)的開
銷明顯大于創(chuàng)建或撤消線程時的開銷摔竿。
2.測試方法
人工測試:個人復查面粮、抽查和會審
機器測試:黑盒測試和白盒測試
2.Heap與stack的差別。
Heap是堆继低,stack是棧熬苍。
Stack的空間由操作系統(tǒng)自動分配/釋放,Heap上的空間手動分配/釋放袁翁。
Stack空間有限柴底,Heap是很大的自由存儲區(qū)
C中的malloc函數(shù)分配的內(nèi)存空間即在堆上,C++中對應的是new操作符。
程序在編譯期對變量和函數(shù)分配內(nèi)存都在棧上進行,且程序運行過程中函數(shù)調(diào)用時參數(shù)的
傳遞也在棧上進行
3.Windows下的內(nèi)存是如何管理的粱胜?
4.介紹.Net和.Net的安全性柄驻。
5.客戶端如何訪問.Net組件實現(xiàn)Web Service?
6.C/C++編譯器中虛表是如何完成的焙压?
7.談談COM的線程模型鸿脓。然后討論進程內(nèi)/外組件的差別抑钟。
8.談談IA32下的分頁機制
小頁(4K)兩級分頁模式,大頁(4M)一級
9.給兩個變量野哭,如何找出一個帶環(huán)單鏈表中是什么地方出現(xiàn)環(huán)的味赃?
一個遞增一,一個遞增二虐拓,他們指向同一個接點時就是環(huán)出現(xiàn)的地方
10.在IA32中一共有多少種辦法從用戶態(tài)跳到內(nèi)核態(tài)心俗?
通過調(diào)用門,從ring3到ring0蓉驹,中斷從ring3到ring0城榛,進入vm86等等
11.如果只想讓程序有一個實例運行,不能運行兩個态兴。像winamp一樣狠持,只能開一個窗
口,怎樣實現(xiàn)瞻润?
用內(nèi)存映射或全局原子(互斥變量)喘垂、查找窗口句柄..
FindWindow,互斥绍撞,寫標志到文件或注冊表,共享內(nèi)存正勒。
67如何截取鍵盤的響應,讓所有的‘a(chǎn)’變成‘b’傻铣?
鍵盤鉤子SetWindowsHookEx
13.Apartment在COM中有什么用章贞?為什么要引入?
14.存儲過程是什么非洲?有什么用鸭限?有什么優(yōu)點?
我的理解就是一堆sql的集合两踏,可以建立非常復雜的查詢败京,編譯運行,所以運行一次后梦染,
以后再運行速度比單獨執(zhí)行SQL快很多
15.Template有什么特點赡麦?什么時候用?
16.談談Windows DNA結(jié)構(gòu)的特點和優(yōu)點弓坞。
網(wǎng)絡編程中設(shè)計并發(fā)服務器隧甚,使用多進程與多線程车荔,請問有什么區(qū)別渡冻?
1,進程:子進程是父進程的復制品忧便。子進程獲得父進程數(shù)據(jù)空間族吻、堆和棧的復制品帽借。
2,線程:相對與進程而言超歌,線程是一個更加接近與執(zhí)行體的概念砍艾,它可以與同進程的其
他線程共享數(shù)據(jù),但擁有自己的椢【伲空間脆荷,擁有獨立的執(zhí)行序列。
兩者都可以提高程序的并發(fā)度懊悯,提高程序運行效率和響應時間蜓谋。
線程和進程在使用上各有優(yōu)缺點:線程執(zhí)行開銷小,但不利于資源管理和保護炭分;而進程
正相反桃焕。同時,線程適合于在SMP機器上運行捧毛,而進程則可以跨機器遷移观堂。
思科
682.找錯題
試題1:
void test1()
{
char string[10];
char* str1 = "0123456789";
strcpy( string, str1 );
}
試題2:
void test2()
{
char string[10], str1[10];
int i;
for(i=0; i<10; i++)
{
str1 = 'a';
}
strcpy( string, str1 );
}
試題3:
void test3(char* str1)
{
char string[10];
if( strlen( str1 ) <= 10 )
{
strcpy( string, str1 );
}
}
解答:
試題1字符串str1需要11個字節(jié)才能存放下(包括末尾的’\0’),而string只有10個字節(jié)的空間呀忧,strcpy會導致數(shù)組越界师痕;
對試題2,如果面試者指出字符數(shù)組str1不能在數(shù)組內(nèi)結(jié)束可以給3分而账;如果面試者指出strcpy(string, str1)調(diào)用使得從str1[url=]內(nèi)存[/url]起復制到string內(nèi)存起所復制的字節(jié)數(shù)具有不確定性可以給7分七兜,在此基礎(chǔ)上指出庫函數(shù)strcpy工作方式的給10分;
對試題3福扬,if(strlen(str1) <= 10)應改為if(strlen(str1) < 10)腕铸,因為strlen的結(jié)果未統(tǒng)計’\0’所占用的1個字節(jié)。
剖析:
考查對基本功的掌握:
(1)字符串以’\0’結(jié)尾铛碑;
(2)對數(shù)組越界把握的敏感度狠裹;
(3)庫函數(shù)strcpy的工作方式,如果編寫一個標準strcpy函數(shù)的總分值為10汽烦,下面給出幾個不同得分的答案:
2分
void strcpy( char strDest, charstrSrc )*
{
while( (
strDest++ = * strSrc++) != ‘\0’ );
}
4分
void strcpy( char strDest, const charstrSrc )*
//將源字符串加const涛菠,表明其為輸入?yún)?shù),加2分
{
while( (
strDest++ = * strSrc++) != ‘\0’ );
}
7分
void strcpy(char strDest, const charstrSrc)*
{
//對源地址和目的地址加非0斷言撇吞,加3分
assert( (strDest != NULL) && (strSrc != NULL) );
while( (
strDest++ = * strSrc++) != ‘\0’ );
}
10分
//為了實現(xiàn)鏈式操作俗冻,將目的地址返回,加3分牍颈!
char * strcpy( char *strDest, const char *strSrc )
{
assert( (strDest != NULL) && (strSrc != NULL) );
charaddress = strDest;
while( (
strDest++ = * strSrc++) != ‘\0’ );
return address;
}
從2分到10分的幾個答案我們可以清楚的看到迄薄,小小的strcpy竟然暗藏著這么多玄機,真不是蓋的煮岁!需要多么扎實的基本功才能寫一個完美的strcpy凹ケ巍涣易!
(4)對strlen的掌握,它沒有包括字符串末尾的'\0'冶伞。
讀者看了不同分值的strcpy版本新症,應該也可以寫出一個10分的strlen函數(shù)了,完美的版本為: int strlen( const char *str ) //輸入?yún)?shù)const
{
assert( strt != NULL ); //斷言字符串地址非0
int len;
while( (*str++) != '\0' )
{
len++;
}
return len;
}
試題4:
void GetMemory( char *p )
{
p = (char *) malloc( 100 );
}
void Test( void )
{
char *str = NULL;
GetMemory( str );
strcpy( str, "hello world" );
printf( str );
}
試題5:
char *GetMemory( void )
{
char p[] = "hello world";
return p;
}
void Test( void )
{
char *str = NULL;
str = GetMemory();
printf( str );
}
試題6:
void GetMemory( char *p, int num )
{
p = (char *) malloc( num );
}
void Test( void )
{
char *str = NULL;
GetMemory( &str, 100 );
strcpy( str, "hello" );
printf( str );
}
試題7:
void Test( void )
{
char *str = (char *) malloc( 100 );
strcpy( str, "hello" );
free( str );
... //省略的其它語句
}
解答:
試題4傳入中GetMemory( char *p )函數(shù)的形參為字符串指針响禽,在函數(shù)內(nèi)部修改形參并不能真正的改變傳入形參的值徒爹,執(zhí)行完
char *str = NULL;
GetMemory( str );
后的str仍然為NULL;
試題5中
char p[] = "hello world";
return p;
的p[]數(shù)組為函數(shù)內(nèi)的局部自動變量芋类,在函數(shù)返回后瀑焦,內(nèi)存已經(jīng)被釋放。這是許多程序員常犯的錯誤梗肝,其根源在于不理解變量的生存期榛瓮。
試題6的GetMemory避免了試題4的問題,傳入GetMemory的參數(shù)為字符串指針的指針巫击,但是在GetMemory中執(zhí)行申請內(nèi)存及賦值語句
*p = (char *) malloc( num );
后未判斷內(nèi)存是否申請成功禀晓,應加上:
if ( *p == NULL )
{
...//進行申請內(nèi)存失敗處理
}
試題7存在與試題6同樣的問題,在執(zhí)行
char *str = (char *) malloc(100);
后未進行內(nèi)存是否申請成功的判斷坝锰;另外粹懒,在free(str)后未置str為空,導致可能變成一個“野”指針顷级,應加上:
str = NULL;
試題6的Test函數(shù)中也未對malloc的內(nèi)存進行釋放凫乖。
剖析:
試題4~7考查面試者對內(nèi)存操作的理解程度,基本功扎實的面試者一般都能正確的回答其中50~60的錯誤弓颈。但是要完全解答正確帽芽,卻也絕非易事。
對內(nèi)存操作的考查主要集中在:
(1)指針的理解翔冀;
(2)變量的生存期及作用范圍导街;
(3)良好的動態(tài)內(nèi)存申請和釋放習慣。
再看看下面的一段程序有什么錯誤:
swap( int* p1,int* p2 )
{
intp;
p =p1;
p1 =p2;
p2 = *p;
}
在swap函數(shù)中纤子,p是一個“野”指針搬瑰,有可能指向系統(tǒng)區(qū),導致程序運行的崩潰控硼。在VC++中DEBUG運行時提示錯誤“Access Violation”泽论。該程序應該改為:
swap( int* p1,int* p2 )
{
int p;
p =p1;
p1 =p2;
p2 = p;
}[img=12,12]file:///D:/魚魚軟件/魚魚多媒體日記本/temp/{56068A28-3D3B-4D8B-9F82-AC1C3E9B128C}_arc_d[1].gif[/img] 3.內(nèi)功題
試題1:分別給出BOOL,int卡乾,float翼悴,指針變量 與“零值”比較的 if 語句(假設(shè)變量名為var)
解答:
BOOL型變量:if(!var)
int型變量: if(var==0)
float型變量:
const float EPSINON = 0.00001;
if ((x >= - EPSINON) && (x <= EPSINON)
指針變量: if(var==NULL)
剖析:
考查對0值判斷的“內(nèi)功”,BOOL型變量的0判斷完全可以寫成if(var==0)说订,而int型變量也可以寫成if(!var)抄瓦,指針變量的判斷也可以寫成if(!var)潮瓶,上述寫法雖然程序都能正確運行陶冷,但是未能清晰地表達程序的意思钙姊。
一般的,如果想讓if判斷一個變量的“真”埂伦、“假”煞额,應直接使用if(var)、if(!var)沾谜,表明其為“邏輯”判斷膊毁;如果用if判斷一個數(shù)值型變量(short、int基跑、long等)婚温,應該用if(var==0),表明是與0進行“數(shù)值”上的比較媳否;而判斷指針則適宜用if(var==NULL)栅螟,這是一種很好的編程習慣。
浮點型變量并不精確篱竭,所以不可將float變量用“==”或“力图!=”與數(shù)字比較,應該設(shè)法轉(zhuǎn)化成“>=”或“<=”形式掺逼。如果寫成if (x == 0.0)吃媒,則判為錯,得0分吕喘。
試題2:以下為Windows NT下的32位C++程序赘那,請計算sizeof的值
void Func ( char str[100] )
{
sizeof( str ) = ?
}
void *p = malloc( 100 );
sizeof ( p ) = ?
解答:
sizeof( str ) = 4
sizeof ( p ) = 4
剖析:
Func ( char str[100] )函數(shù)中數(shù)組名作為函數(shù)形參時,在函數(shù)體內(nèi)氯质,數(shù)組名失去了本身的內(nèi)涵漓概,僅僅只是一個指針;在失去其內(nèi)涵的同時病梢,它還失去了其常量特性胃珍,可以作自增、自減等操作蜓陌,可以被修改觅彰。
數(shù)組名的本質(zhì)如下:
(1)數(shù)組名指代一種數(shù)據(jù)結(jié)構(gòu),這種數(shù)據(jù)結(jié)構(gòu)就是數(shù)組钮热;
例如:
char str[10];
cout << sizeof(str) << endl;
輸出結(jié)果為10填抬,str指代數(shù)據(jù)結(jié)構(gòu)char[10]癌淮。
(2)數(shù)組名可以轉(zhuǎn)換為指向其指代實體的指針丁频,而且是一個指針常量幌绍,不能作自增把鉴、自減等操作,不能被修改宏蛉;
char str[10];
str++; //編譯出錯遣臼,提示str不是左值
(3)數(shù)組名作為函數(shù)形參時,淪為普通指針拾并。
Windows NT 32位平臺下揍堰,指針的長度(占用內(nèi)存的大小)為4字節(jié)嗅义,故sizeof( str ) 屏歹、sizeof ( p ) 都為4。
試題3:寫一個“標準”宏MIN之碗,這個宏輸入兩個參數(shù)并返回較小的一個蝙眶。另外,當你寫下面的代碼時會發(fā)生什么事褪那?
least = MIN(*p++, b);
解答:
define MIN(A,B) ((A) <= (B) ? (A) : (B))
MIN(*p++, b)會產(chǎn)生宏的副作用
剖析:
這個面試題主要考查面試者對宏定義的使用幽纷,宏定義可以實現(xiàn)類似于函數(shù)的功能,但是它終歸不是函數(shù)武通,而宏定義中括弧中的“參數(shù)”也不是真的參數(shù)霹崎,在宏展開的時候?qū)Α皡?shù)”進行的是一對一的替換。
程序員對宏定義的使用要非常小心冶忱,特別要注意兩個問題:
(1)謹慎地將宏定義中的“參數(shù)”和整個宏用用括弧括起來尾菇。所以,嚴格地講囚枪,下述解答:
define MIN(A,B) (A) <= (B) ? (A) : (B)
define MIN(A,B) (A <= B ? A : B )
都應判0分派诬;
(2)防止宏的副作用。
宏定義#define MIN(A,B) ((A) <= (B) ? (A) : (B))對MIN(*p++, b)的作用結(jié)果是:
((p++) <= (b) ? (p++) : (*p++))
這個表達式會產(chǎn)生副作用链沼,指針p會作三次++自增操作默赂。
除此之外,另一個應該判0分的解答是:
define MIN(A,B) ((A) <= (B) ? (A) : (B));
這個解答在宏定義的后面加“;”括勺,顯示編寫者對宏的概念模糊不清缆八,只能被無情地判0分并被面試官淘汰。
試題4:為什么標準頭文件都有類似以下的結(jié)構(gòu)疾捍?
ifndef __INCvxWorksh
define __INCvxWorksh
ifdef __cplusplus
extern "C" {
endif
/.../
ifdef __cplusplus
}
endif
endif /* __INCvxWorksh */
解答:
頭文件中的編譯宏
ifndef __INCvxWorksh
define __INCvxWorksh
endif
的作用是防止被重復引用奈辰。
作為一種面向?qū)ο蟮恼Z言,C++支持函數(shù)重載乱豆,而過程式語言C則不支持奖恰。函數(shù)被C++編譯后在symbol庫中的名字與C語言的不同。例如,假設(shè)某個函數(shù)的原型為:
void foo(int x, int y);
該函數(shù)被C編譯器編譯后在symbol庫中的名字為_foo瑟啃,而C++編譯器則會產(chǎn)生像_foo_int_int之類的名字论泛。_foo_int_int這樣的名字包含了函數(shù)名和函數(shù)參數(shù)數(shù)量及類型信息,C++就是考這種機制來實現(xiàn)函數(shù)重載的蛹屿。
為了實現(xiàn)C和C++的混合編程屁奏,C++提供了C連接交換指定符號extern "C"來解決名字匹配問題,函數(shù)聲明前加上extern "C"后蜡峰,則編譯器就會按照C語言的方式將該函數(shù)編譯為_foo了袁,這樣C語言中就可以調(diào)用C++的函數(shù)了朗恳。 [img=12,12]file:///D:/魚魚軟件/魚魚多媒體日記本/temp/{C74A38C4-432E-4799-B54D-73E2CD3C5206}_arc_d[1].gif[/img]
試題5:編寫一個函數(shù)湿颅,作用是把一個char組成的字符串循環(huán)右移n個。比如原來是“abcdefghi”如果n=2粥诫,移位后應該是“hiabcdefgh”
函數(shù)頭是這樣的:
//pStr是指向以'\0'結(jié)尾的字符串的指針
//steps是要求移動的n
void LoopMove ( char * pStr, int steps )
{
//請?zhí)畛?..
}
解答:
正確解答1:
void LoopMove ( charpStr, int steps )
{
int n = strlen( pStr ) - steps;
char tmp[MAX_LEN];
strcpy ( tmp, pStr + n );
strcpy ( tmp + steps, pStr);
( tmp + strlen ( pStr ) ) = '\0';
strcpy( pStr, tmp );
}
正確解答2:
void LoopMove ( char *pStr, int steps )
{
int n = strlen( pStr ) - steps;
char tmp[MAX_LEN];
memcpy( tmp, pStr + n, steps );
memcpy(pStr + steps, pStr, n );
memcpy(pStr, tmp, steps );
}
剖析:
這個試題主要考查面試者對標準庫函數(shù)的熟練程度油航,在需要的時候引用庫函數(shù)可以很大程度上簡化程序編寫的工作量。
最頻繁被使用的庫函數(shù)包括:
(1) strcpy
(2) memcpy
(3) memset
作者:Style_偉
鏈接:http://www.reibang.com/p/ee07448348ee
來源:簡書
著作權(quán)歸作者所有怀浆。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)谊囚,非商業(yè)轉(zhuǎn)載請注明出處。
( 其實作為一個開發(fā)者有一個學習的氛圍跟一個交流圈子特別重要执赡,這是我的一個iOS交流群镰踏,不管是小白還是大牛都歡迎入駐,大家一起交流成長沙合! )