問題描述
我知道使用 RTTI 會影響資源,但影響有多大?我看過的所有地方都只是說RTTI 很貴",但實際上沒有一個提供任何基準(zhǔn)或定量數(shù)據(jù)來保護(hù)內(nèi)存、處理器時間或速度.
I understand that there is a resource hit from using RTTI, but how big is it? Everywhere I've looked just says that "RTTI is expensive," but none of them actually give any benchmarks or quantitative data reguarding memory, processor time, or speed.
那么,RTTI 有多貴?我可能會在只有 4MB 內(nèi)存的嵌入式系統(tǒng)上使用它,所以每一位都很重要.
So, just how expensive is RTTI? I might use it on an embedded system where I have only 4MB of RAM, so every bit counts.
根據(jù) S. Lott 的回答,這樣會更好如果我包括我實際在做的事情.我正在使用一個類來傳遞不同長度的數(shù)據(jù)并且可以執(zhí)行不同的操作,因此使用只有虛函數(shù).似乎使用幾個 dynamic_cast
可以解決這個問題,允許不同的派生類通過不同的級別,但仍然允許它們以完全不同的方式運行.
As per S. Lott's answer, it would be better if I include what I'm actually doing. I am using a class to pass in data of different lengths and that can perform different actions, so it would be difficult to do this using only virtual functions. It seems that using a few dynamic_cast
s could remedy this problem by allowing the different derived classes to be passed through the different levels yet still allow them to act completely differently.
根據(jù)我的理解,dynamic_cast
使用 RTTI,所以我想知道在有限的系統(tǒng)上使用它有多可行.
From my understanding, dynamic_cast
uses RTTI, so I was wondering how feasable it would be to use on a limited system.
推薦答案
不管編譯器如何,只要你負(fù)擔(dān)得起,你總是可以節(jié)省運行時間
Regardless of compiler, you can always save on runtime if you can afford to do
if (typeid(a) == typeid(b)) {
B* ba = static_cast<B*>(&a);
etc;
}
代替
B* ba = dynamic_cast<B*>(&a);
if (ba) {
etc;
}
前者只涉及std::type_info
的一個比較;后者必然涉及遍歷繼承樹和比較.
The former involves only one comparison of std::type_info
; the latter necessarily involves traversing an inheritance tree plus comparisons.
過去……就像大家說的那樣,資源使用是特定于實現(xiàn)的.
Past that ... like everyone says, the resource usage is implementation specific.
我同意其他人的意見,即提交者出于設(shè)計原因應(yīng)避免使用 RTTI.然而,使用 RTTI 有很好的理由(主要是因為 boost::any).請記住,了解其在常見實現(xiàn)中的實際資源使用情況很有用.
I agree with everyone else's comments that the submitter should avoid RTTI for design reasons. However, there are good reasons to use RTTI (mainly because of boost::any). That in mind, it's useful to know its actual resource usage in common implementations.
我最近對 ??GCC 中的 RTTI 進(jìn)行了大量研究.
I recently did a bunch of research into RTTI in GCC.
tl;dr: GCC 中的 RTTI 使用的空間可以忽略不計,并且 typeid(a) == typeid(b)
在許多平臺上(Linux、BSD 和嵌入式平臺,但不是 mingw32)非常快).如果您知道自己將永遠(yuǎn)在一個受祝福的平臺上,那么 RTTI 非常接近免費.
tl;dr: RTTI in GCC uses negligible space and typeid(a) == typeid(b)
is very fast, on many platforms (Linux, BSD and maybe embedded platforms, but not mingw32). If you know you'll always be on a blessed platform, RTTI is very close to free.
重要細(xì)節(jié):
GCC 更喜歡使用特定的供應(yīng)商中立"C++ ABI[1],并且始終將此 ABI 用于 Linux 和 BSD 目標(biāo)[2].對于支持此 ABI 和弱鏈接的平臺,typeid()
為每種類型返回一致且唯一的對象,甚至跨越動態(tài)鏈接邊界.您可以測試 &typeid(a) == &typeid(b)
,或者僅依賴于便攜式測試 typeid(a) == typeid(b)
實際上只是在內(nèi)部比較一個指針.
GCC prefers to use a particular "vendor-neutral" C++ ABI[1], and always uses this ABI for Linux and BSD targets[2]. For platforms that support this ABI and also weak linkage, typeid()
returns a consistent and unique object for each type, even across dynamic linking boundaries. You can test &typeid(a) == &typeid(b)
, or just rely on the fact that the portable test typeid(a) == typeid(b)
does actually just compare a pointer internally.
在 GCC 的首選 ABI 中,類 vtable 總是 持有一個指向每個類型的 RTTI 結(jié)構(gòu)的指針,盡管它可能不被使用.因此,typeid()
調(diào)用自身應(yīng)該只花費與任何其他 vtable 查找(與調(diào)用虛擬成員函數(shù)相同)的成本,并且 RTTI 支持 應(yīng)該't 為每個對象使用任何額外的空間.
In GCC's preferred ABI, a class vtable always holds a pointer to a per-type RTTI structure, though it might not be used. So a typeid()
call itself should only cost as much as any other vtable lookup (the same as calling a virtual member function), and RTTI support shouldn't use any extra space for each object.
據(jù)我所知,GCC 使用的 RTTI 結(jié)構(gòu)(這些都是 std::type_info
的子類)只為每種類型保存幾個字節(jié),除了名稱.即使使用 -fno-rtti
,我也不清楚輸出代碼中是否存在名稱.無論哪種方式,編譯后的二進(jìn)制文件大小的變化都應(yīng)該反映運行時內(nèi)存使用的變化.
From what I can make out, the RTTI structures used by GCC (these are all the subclasses of std::type_info
) only hold a few bytes for each type, aside from the name. It isn't clear to me whether the names are present in the output code even with -fno-rtti
. Either way, the change in size of the compiled binary should reflect the change in runtime memory usage.
一個快速實驗(在 Ubuntu 10.04 64 位上使用 GCC 4.4.3)表明 -fno-rtti
實際上增加一個簡單測試程序的二進(jìn)制大小幾百字節(jié).這在 -g
和 -O3
的組合中一致發(fā)生.我不確定為什么尺寸會增加;一種可能性是 GCC 的 STL 代碼在沒有 RTTI 的情況下表現(xiàn)不同(因為異常不起作用).
A quick experiment (using GCC 4.4.3 on Ubuntu 10.04 64-bit) shows that -fno-rtti
actually increases the binary size of a simple test program by a few hundred bytes. This happens consistently across combinations of -g
and -O3
. I'm not sure why the size would increase; one possibility is that GCC's STL code behaves differently without RTTI (since exceptions won't work).
[1] 稱為 Itanium C++ ABI,記錄在 http://www.codesourcery.com/public/cxx-abi/abi.html.名稱非常混亂:名稱指的是原始開發(fā)架構(gòu),盡管 ABI 規(guī)范適用于許多架構(gòu),包括 i686/x86_64.GCC 內(nèi)部源代碼和 STL 代碼中的注釋將 Itanium 稱為新"ABI,與他們之前使用的舊"ABI 形成對比.更糟糕的是,新"/安騰 ABI 指的是通過 -fabi-version
可用的所有版本;舊" ABI 早于此版本控制.GCC 在 3.0 版本中采用了 Itanium/versioned/"new" ABI;如果我正確閱讀了他們的變更日志,則在 2.95 及更早版本中使用了舊"ABI.
[1] Known as the Itanium C++ ABI, documented at http://www.codesourcery.com/public/cxx-abi/abi.html. The names are horribly confusing: the name refers to the original development architecture, though the ABI specification works on lots of architectures including i686/x86_64. Comments in GCC's internal source and STL code refer to Itanium as the "new" ABI in contrast to the "old" one they used before. Worse, the "new"/Itanium ABI refers to all versions available through -fabi-version
; the "old" ABI predated this versioning. GCC adopted the Itanium/versioned/"new" ABI in version 3.0; the "old" ABI was used in 2.95 and earlier, if I am reading their changelogs correctly.
[2] 我找不到按平臺列出std::type_info
對象穩(wěn)定性的任何資源.對于我可以訪問的編譯器,我使用了以下內(nèi)容:echo "#include
.從 GCC 3.0 開始,此宏在 GCC 的 STL 中控制 operator==
對于 std::type_info
的行為.我確實發(fā)現(xiàn) mingw32-gcc 遵守 Windows C++ ABI,其中 std::type_info
對象對于跨 DLL 的類型不是唯一的;typeid(a) == typeid(b)
在幕后調(diào)用 strcmp
.我推測在像 AVR 這樣沒有代碼鏈接的單程序嵌入式目標(biāo)上,std::type_info
對象總是穩(wěn)定的.
[2] I couldn't find any resource listing std::type_info
object stability by platform. For compilers I had access to, I used the following: echo "#include <typeinfo>" | gcc -E -dM -x c++ -c - | grep GXX_MERGED_TYPEINFO_NAMES
. This macro controls the behavior of operator==
for std::type_info
in GCC's STL, as of GCC 3.0. I did find that mingw32-gcc obeys the Windows C++ ABI, where std::type_info
objects aren't unique for a type across DLLs; typeid(a) == typeid(b)
calls strcmp
under the covers. I speculate that on single-program embedded targets like AVR, where there is no code to link against, std::type_info
objects are always stable.
這篇關(guān)于RTTI有多貴?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!