Recently saw the Boost::any class source, its implementation is mainly dependent on the typeid operator. Wondering how much time and space overhead it would take to make a decision.
VS2008 included with the Type_info class only header files, no source files, declared as follows:
[CPP]View Plaincopy
- Class Type_info {
- Public
- virtual ~type_info ();
- _crtimp_pure bool __clr_or_this_call operator== (const type_info& RHS) const;
- _crtimp_pure bool __clr_or_this_call operator!= (const type_info& RHS) const;
- _crtimp_pure int __clr_or_this_call before (const type_info& RHS) const;
- _crtimp_pure const char* __clr_or_this_call name (__type_info_node* __ptype_info_node = &__type_info_root_ node) const;
- _crtimp_pure const char* __clr_or_this_call raw_name () const;
- Private
- void *_m_data;
- Char _m_d_name[1];
- __clr_or_this_call type_info (const type_info& RHS);
- type_info& __clr_or_this_call operator= (const type_info& RHS);
- _crtimp_pure static const char *__clrcall_or_cdecl _name_base (const type_info *,__type_info_node* __ Ptype_info_node);
- _crtimp_pure static void __clrcall_or_cdecl _type_info_dtor (type_info *);
- };
Test code:
[CPP]View Plaincopy
- #include <iostream>
- Using namespace std;
- Class Object
- {
- };
- int main ()
- {
- Object obj;
- cout << "type name:" << typeid (obj). Name () << Endl;
- cout << "type raw name:" << typeid (obj). Raw_name () << Endl;
- if (typeid (obj) = = typeID (Object))
- {
- cout << "type is equal" << Endl;
- }
- Else
- {
- cout << "type is not equal" << Endl;
- }
- return 0;
- }
Output:
Type Name:class Object
Type Raw Name:[email protected]@
Type is equal
Before explaining how each function is implemented, look at how the Type_info class is stored.
typeID returns a reference to Type_info, which cannot be copied or constructed by itself, so there is at most one type_info of data for each class, where is this data stored?
Open exe file with UltraEdit, search "Object", can find this string. Then open the EXE with the PE tool and find that the string belongs to the data section (this is a readable and writable global data segment). Then the typeID code is commented, the PE file does not have this string. Come to a conclusion:
The compiler generates a copy of the type_info data stored in the data segment for each type of typeid operation.
How big is this data? Look at the following code:
[CPP]View Plaincopy
- #include <iostream>
- Using namespace std;
- Class Object
- {
- };
- int main ()
- {
- const type_info* p = &typeid (Object);
- cout << p << Endl;
- return 0;
- }
In the cout line, under Breakpoint, view the value of P to:
Looking again at the declaration of this class, the destructor is of type virtual, so the first four bytes of P are virtual function tables. The p+4 is a _m_data,void* type, four bytes, and is found to be 0 when debugging, and it is unclear what it means.
The p+8 is an array of _m_d_name,char types, and the raw_name is stored, and the raw_name size of each type is variable, so the array length is 1. The TYPE_INFO storage structure is now at a glance:
The length of each type of type_info data depends on the type name, at least 9 bytes.
Now suppose that a complex project has 50 types with the typeid operator, with an average length of 24 per type_info, which increases the PE size to 1200B, about 1 K. And now the PE is dozens of m, so this space overhead is nothing at all.
And look at the overhead of these function calls:
- The Raw_name function returns the address of the _m_d_name directly, very fast;
- The name function decodes the _m_d_name stored string into its actual name, which is also fast;
- The = = operator is the comparison of Raw_name is equal, also very soon.
Readers may have two doubts:
- Why not store it directly as a name? I think the biggest reason is to save space, such as double raw_name for ". N ", name is" double "four bytes more.
- The = = operator Why not directly compare two type_info referenced addresses are equal? I am also very puzzled, I see the sink code found it is relatively raw_name.
Note: C + + does not specify typeID implementation criteria, each compiler may be different, the above analysis process is based on the VS2008 of the compiler.
Summary: Thetime and space cost of typeid is very small, but when used, try not to violate the open closure principle.
http://blog.csdn.net/passion_wu128/article/details/38441633
C + + typeID implementation principle