我的問題就像標題所說的那樣。顯然,第一個參數是用於這個指針的,有些C++的味道,第二個呢?謝謝你。「id(* IMP)(id,SEL,...)」中的第二個參數用於什麼?
回答
的objc_msgSend()
的簽名是:
id objc_msgSend(id self, SEL op, ...);
每一個方法調用被編譯成這個函數的調用。也就是說,如果您撥打:
[anArray objectAtIndex:42];
將編譯,就像它是:現在
objc_msgSend(anArray, @selector(objectAtIndex:), 42);
,你的問題,爲什麼get方法編譯成具有SEL作爲一個功能第二個論點。或者,更具體地講,這是爲什麼方法:
- (id)objectAtIndex:(NSUInteger)index;
完全等同於這個C函數:
id object_at_index(id object, SEL _cmd, NSUInteger index);
答案是速度速度速度。
速度具體地,通過這樣做,則objc_msgSend()
從來沒有重寫堆棧幀*和它也可以使用一個尾調用優化的直接跳轉到的方法調用。這與你在調試器中不會看到objc_msgSend()
回溯的原因是相同的(除了當你實際在信使中崩潰時)。
objc_msgSend()
使用object
和_cmd
來查找該方法的實現,然後毫不誇張地說,跳轉到該實現。
非常快。堆棧幀不變。
而且,正如其他人所說的,在方法實現中具有_cmd
可能由於各種原因而得心應手。同樣,這也意味着信使可以通過NSInvocation等做類似於代理支持的整潔技巧。
*重寫堆棧幀可能非常複雜和昂貴。某些參數可能在某些時候處於寄存器中,等等......所有體系結構都依賴於ABI nastiness。編寫像imp_implementationWithBlock()
這樣的東西最大的挑戰之一就是想知道如何做到這一點而不用觸摸堆棧,因爲這樣做會太慢,太臃腫而不可行。
從文檔:
討論
此數據類型是一個指向實現該方法的功能的開始。該函數使用當前CPU體系結構實現的標準C調用約定。第一個參數是一個指向自我的指針(即,該類的特定實例的內存,或者對於類方法而言,指向該元類的指針)。第二個參數是方法選擇器。方法參數如下。
在Objective-C中,當你調用一個方法時,你需要知道目標,選擇器和最終的參數。假設您正在嘗試手動執行此操作:如果您不知道選擇器,如何知道要調用哪個方法?你打電話給一些隨機的方法嗎?不,您會調用正確的方法,因爲您知道方法名稱。
嗨,@Ramy Al Zuhouri。我知道第二個參數是方法選擇器(SEL),它簽署了用於查找方法的消息。但爲什麼要成爲任何方法的第二個參數。我不明白這種情況會帶來什麼好處,就像用於訪問類方法的fisrt參數,memeber var,metaclass一樣。但第二個參數呢 –
在C++中,方法調用至少由兩部分組成:目標和方法名稱。像obj.myMethod()。那麼第二個參數是用來區分我們想要調用的方法。在Objective-C中將是@selector(myMethod)。 –
也許你可以詳細說明這一點。逐字引用Apple的文檔遠不是一個可以接受的答案。 – CodaFi
使第二個參數包含選擇器的目的是啓用通用調度機制。因此,方法調度代碼總是希望第二個參數成爲選擇器,並根據該調度進行調度,或者遵循繼承鏈,甚至創建一個NSInvocation
並調用forwardInvocation:
。
一般情況下,只有系統級的程序使用選擇的說法,雖然這是相當不錯的,它的時候你打的異常或在調試器試圖找出什麼程序是給你的困難,如果你正在使用forwardInvocation
- 1. 什麼是NSLocalizedString()的第二個參數?
- 2. 更改每個第二個ID組數據幀的ID列
- 3. 第二個參數是什麼?
- 4. 爲什麼隱式轉換不適用於第二個參數?
- 5. 在ruby中,CSV.open()的第二個參數/參數是什麼?
- 6. 目標C用於使用SEL和IMP進行環路優化
- 7. 什麼用於登錄ID?
- 8. 什麼是「+ id +」用於?
- 9. 什麼是id用於?
- 10. getline中第二個參數的用途是什麼?
- 11. cffunction:基於第一個參數的第二個參數
- 12. ListView中的AddHeaderView中的第二個參數是做什麼的?
- 13. 模型中的第二個參數是什麼(「pagemodel」,'pages')
- 14. date函數中的第二個參數是什麼意思?
- 15. 第二個lambda中的參數是做什麼的?
- 16. 複製數據幀用於第二主體ID
- 17. 當id作爲函數的第一個參數傳遞時,jQuery實現了什麼$(id)?
- 18. std :: enable_if的第二個參數有什麼用?
- 19. Ruby中TCPSocket.send的第二個參數是什麼?
- 20. Rails動態查找器中的第二個參數是什麼?
- 21. std :: vector.resize()中的第二個參數是什麼意思?
- 22. savedInstanceState.getInt中的第二個參數是什麼?
- 23. 在Python Flask中Session.pop方法的第二個參數是什麼?
- 24. 什麼是ClassPathXmlApplicationContext中的第二個參數(String path,<?> clazz)
- 25. Matlab:max(A,[],dim)中的第二個參數是什麼意思?
- 26. SQL:從第二大ID
- 27. 在libgdx中用於VertexAttribute()的第三個參數是什麼?
- 28. 爲什麼第二個參數不是基於第一個參數的標準進行過濾?
- 29. 爲什麼第二個route.MapRoute同一個控制器得到一個空ID
- 30. 爲什麼我的遞歸函數沒有第二個參數?
嗨,@ bbum。我沒有在GNUSTEP上使用objc_msgSend而不是objc_msglookup。我看看GNUSTEP的objc_msglookup源代碼,它完全由ASM語言編寫,用於加速。用於查找IMP的asm代碼,並返回obj_msgSend找到的內容。最後,返回的IMP的調用返回給objc_msglookup的調用者,然後由調用者執行。順便說一下,你能告訴我什麼是tail調用objc_msgSend的優化是編譯器優化行爲還是編程技巧? –
Here:http://www.friday.com/bbum/2009/12/18/objc_msgsend-part-1-the-road-map/ GNUSTEP objc運行時與Apple運行時非常相似。如果他們不使用尾部呼叫作爲優化,我會感到驚訝(在上面的鏈接中解釋了尾部呼叫優化)。 – bbum
是的,你可以看看它的實現http://svn.gna.org/svn/gnustep/libs/libobjc2/trunk/objc_msgSend.x86-32.S –