2013-07-04 4 views
3

일부 C++ 표준 라이브러리 클래스에서 호기심을 가지고 sizeof() 연산자를 적용했습니다. 여기에 내가 관찰 한 것입니다 : 내 시스템 (64 비트)에C++ 표준 라이브러리의 sizeof()

int main() 
{ 
    vector<double> v1; 
    set<double> s1; 
    map<double,double> m1; 

    stack<char> st; 
    queue<char> q; 

    vector<char> v2; 
    set<char> s2; 
    map<char,char> m2; 

    cout<<sizeof(v1)<<" "<<sizeof(s1)<<" "<<sizeof(m1)<<endl; 
    cout<<sizeof(v2)<<" "<<sizeof(s2)<<" "<<sizeof(m2)<<endl; 
    cout<<sizeof(q)<<" "<<sizeof(st)<<endl; 
    return 0; 
} 

출력은 다음과 같습니다

12 24 24 
12 24 24 
40 40 

나는 std::set 구현을 위해 레드 - 블랙 트리를 사용하는 것을 알고있다. 따라서 이진 트리의 각 노드에는 두 개의 포인터 (각각 8 바이트)가 있고 값 (8 바이트, 총 24)은 괜찮은 것 같습니다.

  1. std::map는 여전히 24 바이트 (또한 레드 - 블랙 트리를 사용) 별도의 키를 가지고 있지만? 왜?

  2. 왜 과 std::stack은 40 바이트를 차지하지만 std::vector은 12 바이트 만 사용합니까?

  3. chardouble이 클래스 크기에 영향을주지 않는 이유는 무엇입니까? 템플릿 때문입니까?

+3

'sizeof'는 함수가 아니라 C++ 언어로 정의 된 연산자와 키워드입니다. –

+0

@BasileStarynkevitch 질문을 업데이트했습니다. – banarun

+2

왜 sizeof (container) == sizeof (node)를 기대합니까? –

답변

5

sizeof 운영자가 당신에게의 크기를 줄 것이다 : 실제로 배열이 아닌 포인터, 이러한 (배열 종류와 크기 모두) 중요 할을 유지하는 표준 : : 배열에 대한

유형.

여기에 std::vector<T>의 매우 단순화 된 버전을 작성하면됩니다 (실제 구현이하는 것만 큼 아무 것도하지 않으며 실제로 작동하기에는 너무 단순 해집니다. 당신이 정말 진짜 필요한 비트 많이) :

template<typename T> 
class vector<T> 
{ 
    public: 
     typedef size_t size_type; 
    private: 
    T* mdata; 
    size_type msize; 
    size_type mreserved; 
    public: 
    vector() { mreserved = msize = 0; mdata = 0; } 
    vector(size_type sz) { msize = 0; mreserved = sz; mdata = new T[sz](); } 
    void push_back(const T& v) 
    { 
     if (msize + 1 > mreserved) grow(mreserved * 2); 
     mdata[msize+1] = v; 
     msize++; 
    } 
    size_type size() const { return msize; } 
    // bunch of other public functions go here. 
    private: 
    void grow(size_type newsize) 
    { 
     if (newsize < 8) newsize = 8; 
     T* newdata = new T[newsize]; 
     for(size_type i = 0; i < msize; i++) newdata[i] = mdata[i]; 
     swap(mdata, newdata); 
     delete [] mdata; 
     mreserved = newsize; 
    } 
    }; 

당신이 볼 수 있듯이, 실제 클래스의 크기가 (이 동일한 크기와 요소의 수를 포함) 아무리 큰 세트와 동일합니다 저장된 데이터의 즉, sizeof(vector<int>)은 상수입니다. mdata 뒤에 저장된 데이터의 크기는 물론 변경되지만 sizeof은 알 수 없습니다 (알 수 없음).

6

이러한 클래스의 구현은 블랙 박스이므로 포함 된 데이터 또는 개인 멤버를 알 수있는 방법이 없습니다. 그것은 완전히 구현까지입니다.

개체 인스턴스의 모든 바이트가 무엇인지 알 수있는 유일한 방법은 소스 코드를 읽는 것입니다.

+0

sizeof()는 비공개 또는 공개 멤버와 상관없이 클래스의 크기를 알려주지 않습니까? – banarun

+0

@banarun : 네, 그렇습니다. –

+1

@banarun 그렇습니다. 'sizeof'는 모든 멤버의 크기를 반환하지만, 여러분은 그것이 무엇인지 모릅니다. 클래스의 크기가 24 바이트라고해서 3 개의 포인터가 있다는 것을 의미하지는 않습니다. –

2

sizeof은 컴파일시 일 때 평가되므로 기억해 두어야합니다.

그 역할은 클래스/구조체/일반 오래된 데이터의 크기를 반환하는 것입니다. 아무것도.

그래서 항상 벡터, 세트 및지도에 대해 동일한 결과를 제공합니다.

2

컨테이너 클래스의 크기가 소비되는 요소의 수와 함께 증가 할 수 있다고 가정하는 것처럼 보이지만, 모든 유형이 고정 크기이므로 물리적으로 불가능합니다.

대신 요소는 동적 할당을 사용하여 간접적으로 저장됩니다.
sizeof은이 정보를 사용자에게 공개하지 않습니다..

sizeof 정보는 컨테이너의 구성 및 관리에 사용 된 포인터, 카운터, 플래그 및 기타 메타 데이터의 수를 나타냅니다. 이런 종류의 세부 사항은 당신에게서 추상화되어 있습니다. 그리고 결코 그것에 대해 합리화하려고 시도해서는 안됩니다.

4

이 샘플 소스 코드는 당신에게 아이디어를 줄 것이다 :

struct A 
{ 
    int* p; //4 bytes 
    A(int n) 
    { 
     p = new int[n]; 
    } 
}; 

int main() 
{ 
    A x1(10); 
    A x2(100); 
    cout << boolalpha << (sizeof(x1) == sizeof(x2)); //prints true 
} 

이유는 A가 포인터 만이 포함되어 있다는 것입니다. 포인터의 크기는 항상 동일합니다 (보통 4). 포인터가 가리키는 것이 중요하지 않습니다. 동적 배열 1000 또는 1000000입니다. 여전히 4입니다.

char 또는 double은 char 포인터가 double 포인터와 크기가 같기 때문에 크기에 영향을주지 않습니다.

cout << boolalpha << ((sizeof(std::array<int, 10>) == sizeof(std::array<int, 11>)); //false! 
cout << boolalpha << ((sizeof(std::array<int, 10>) == sizeof(std::array<long double, 10>)); //false! 
관련 문제