文字列を静的に割り当てる方法に関するすべての回答が気に入っていますが、すべての実装、特に元のポスターがリンクされているドキュメントの実装に必ずしも当てはまるとは限りません。この場合、装飾された型名はスペースを節約するために静的に格納され、装飾されていない型名はオンデマンドで計算され、リンクされたリストにキャッシュされます。
Visual C++ のtype_info::name()
実装がメモリをどのように割り当ててキャッシュするかについて知りたい場合は、簡単に見つけることができます。まず、小さなテスト プログラムを作成します。
#include <cstdio>
#include <typeinfo>
#include <vector>
int main(int argc, char* argv[]) {
std::vector<int> v;
const type_info& ti = typeid(v);
const char* n = ti.name();
printf("%s\n", n);
return 0;
}
それをビルドしてデバッガー (私は WinDbg を使用) で実行し、 によって返されたポインターを確認しますtype_info::name()
。それはグローバル構造を指していますか?その場合、WinDbg のln
コマンドは最も近いシンボルの名前を教えてくれます。
0:000> ?? n
char * 0x00000000`00857290
"class std::vector<int,class std::allocator<int> >"
0:000> ln 0x00000000`00857290
0:000>
ln
これは、文字列が特定のモジュールが所有するアドレスの範囲内になかったことを示しています。データまたは読み取り専用データ セグメント内にある場合は、その範囲内になります。によって返されたアドレスをすべてのヒープで検索して、ヒープに割り当てられているかどうかを確認しましょうtype_info::name()
。
0:000> !heap -x 0x00000000`00857290
Entry User Heap Segment Size PrevSize Unused Flags
-------------------------------------------------------------------------------------------------------------
0000000000857280 0000000000857290 0000000000850000 0000000000850000 70 40 3e busy extra fill
はい、ヒープに割り当てられました。プログラムの先頭にブレークポイントを置いてmalloc()
再起動すると、それが確認されます。
の宣言を見ると<typeinfo>
、ヒープ ポインターがキャッシュされている場所の手がかりが得られます。
struct __type_info_node {
void *memPtr;
__type_info_node* next;
};
extern __type_info_node __type_info_root_node;
...
_CRTIMP_PURE const char* __CLR_OR_THIS_CALL name(__type_info_node* __ptype_info_node = &__type_info_root_node) const;
のアドレスを見つけて__type_info_root_node
、デバッガーでリストをたどると、 によって返されたのと同じアドレスを含むノードがすぐに見つかりますtype_info::name()
。リストはキャッシュスキームに関連しているようです。
元の質問にリンクされている MSDN ページは、空白を埋めているようです。名前は、スペースを節約するために装飾された形式で保存されており、このフォームには からアクセスできますtype_info::raw_name()
。type_info::name()
特定の型で初めて呼び出すと、名前の装飾が解除され、ヒープに割り当てられたバッファーに格納され、バッファー ポインターがキャッシュされて返されます。
リンクされたリストは、プログラムの終了時にキャッシュされた文字列の割り当てを解除するためにも使用できます (ただし、そうであるかどうかは確認していません)。これにより、メモリ デバッグ ツールを実行したときにメモリ リークとして表示されなくなります。