C++에서 typeid 실현 원리 에 대한 상세 한 설명

4107 단어 c + +typeid의 원리
최근 boost::any 류 소스 코드 를 보 았 습 니 다.주로 typeid 연산 자 에 의존 합 니 다.이렇게 이 루어 지 는 시간 과 공간 비용 이 얼마나 되 는 지 궁금 해 결말 을 알 아 보기 로 했다.
VS 2008 첨부 typeinfo 클래스 는 헤더 파일 만 있 고 원본 파일 은 없습니다.다음 과 같이 설명 합 니 다.

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 *);
};
테스트 코드:

#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;
}
출력:
type name:class Object
type raw name:.?AVObject@@
type is equal
각 함수 의 실현 원 리 를 설명 하기 전에 typeinfo 클래스 의 저장 방식.
typeid 는 type 를 되 돌려 줍 니 다.info 의 인용,이 종 류 는 복사 할 수 없고 스스로 구성 할 수 없 기 때문에 각 종 류 는 최대 하나의 type 만 있 습 니 다.info 데이터,이 데 이 터 는 어디 에 저장 되 어 있 습 니까?
UltraEdit 로 exe 파일 을 열 고"Object"를 검색 하면 이 문자열 을 찾 을 수 있 습 니 다.PE 도구 로 이 exe 를 열 면 이 문자열 이 data 절 에 속 하 는 것 을 발견 합 니 다.(읽 고 쓸 수 있 는 전역 데이터 세그먼트 입 니 다.)type:id 가 있 는 코드 를 모두 주석 하면 PE 파일 에 이 문자열 이 없습니다.결론 을 얻다.
컴 파일 러 는 모든 typeid 작업 의 유형 에 데이터 세그먼트 에 저 장 된 type 을 생 성 합 니 다.info 데이터.
이 데 이 터 는 얼마나 큽 니까?다음 코드 를 보십시오.

#include <iostream>
using namespace std;
 
class Object
{
};
 
int main()
{
	const type_info* p = &typeid(Object);
	cout << p << endl;
	return 0;
}
cout 의 줄 아래 정지점 에서 p 의 값 을 볼 수 있 습 니 다:

이 종류의 성명 을 다시 보 세 요.석조 함 수 는 virtual 형식 이기 때문에 p 의 첫 번 째 4 바이트 는 가상 함수 표 입 니 다.p+4 는m_data,void*형식,네 개의 바이트,디 버 깅 할 때 모두 0 인 것 을 발 견 했 습 니 다.무엇 을 표시 하 는 지 잘 모 르 겠 습 니 다.
p+8 은m_d_name,char 형식 배열,raw 저장name,각 유형의 rawname 크기 가 길 지 않 기 때문에 배열 길 이 는 1 입 니 다.현재 typeinfo 의 저장 구 조 는 이미 일목요연 하 다.
유형 별 typeinfo 데이터 길 이 는 형식 이름 에 의존 합 니 다.최소 9 개의 바이트 입 니 다.
현재 복잡 한 프로젝트 에 50 개의 유형 이 type:id 연산 자 를 사용 했다 고 가정 합 니 다.평균 type:info 길 이 는 24 이 며,이 데이터 에 추 가 된 PE 크기 는 1200 B 로 1K 정도 입 니 다.현재 PE 는 걸핏하면 몇 십 M 이기 때문에 이 정도 의 공간 지출 은 아무것도 아니다.
이 함수 호출 비용 을 다시 보 세 요:
  • raw_name 함수 바로 돌아 가기m_d_name 주소 가 아주 빠 릅 니 다
  • name 함수 장m_d_name 에 저 장 된 문자열 을 실제 이름 으로 디 코딩 하 는 것 도 빠 릅 니 다
  • ==연산 자 는 비교 rawname 이 같은 지 여부 도 빠 릅 니 다.
  • 독자 들 은 두 가지 의혹 이 있 을 수 있다.
    4.567917.저장 할 때 왜 name 으로 직접 저장 하지 않 습 니까?가장 큰 이 유 는 공간 을 절약 하 는 것 이 라 고 생각 합 니 다.예 를 들 어 double 의 rawname 은"N"이 고 name 은"double"입 니 다
  • ==연산 자 는 왜 두 type 를 직접 비교 하지 않 습 니까?info 가 인용 한 주 소 는 같 습 니까?저도 의 심 스 럽 습 니 다.외환 코드 를 보 니 raw 인 것 같 습 니 다.name。
  • 비고:C++는 typeid 실현 기준 을 규정 하지 않 았 습 니 다.각 컴 파일 러 는 다 를 수 있 습 니 다.상기 분석 과정 은 VS 2008 자체 컴 파일 러 를 바탕 으로 합 니 다.
    결론:typeid 가 가 져 온 시간 과 공간 비용 은 매우 작 지만 사용 할 때 개방 폐쇄 원칙 을 어기 지 않도록 한다.
    C++에서 typeid 의 실현 원리 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 C++typeid 의 실현 원리 에 관 한 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 바 랍 니 다!

    좋은 웹페이지 즐겨찾기