2012-08-03 6 views
17

T 유형의 경우 std::list<T> 유형이 동일하고 일정한 크기를 유지한다고 가정 할 수 있습니까? 그냥 명확하게하기 위해, 나는 '메인'타입 자체의 크기를 의미하며, 그것에 의해 할당 된 메모리는 아닙니다.sizeof (std :: list <T>)는 다양한 유형의 T?

T 자체의 크기는 할당자를 사용하여 할당 된 목록 노드의 크기에만 영향을 주어야한다고 가정하는 것이 논리적 인 것처럼 보입니다.

그러나 내가 생각할 수있는 sizeof(std::list<T>)의 variancy가 발생할 수 있습니다 두 가지가 있습니다 :

  1. '최적화'를 std::list<T> 자체에 T 인스턴스의 일부를 바꾸어 std::list 유형에 시도하는 표준 C++ 라이브러리 . 그건 나에게 나쁜 생각 인 것 같고 표준에 의해 요구되는 '일정한 시간'요구 사항을 깨뜨릴 수 있습니다.
  2. 전문화가 다른 크기 인 일부 유형의 경우 라이브러리 특수화가 std::list<T> 인 표준 C++입니다.

(1) 또는 (2)에 대한 용도는 생각할 수 없지만 잘못되었을 수 있습니다.

내가 달성하려는 생각은 내부에 std::list<T>을 사용하는 템플릿 클래스에 고정 크기 슬라이스 할당자를 사용하는 것입니다. 참고로


:이은 T의 다른 유형의 차이에 대해, 그리고 다른 할당 자에 대한 하지. 모든 인스턴스화를 명시 적으로 제어 할 것이고 모두는 std::allocator을 사용할 것입니다.

+0

흥미 롭습니다. +1. 나는 꽤 확신한다. 표준은 같은 크기를 보장하지 않지만 여전히 +1과 그냥 주석이다. –

+0

나는이 생각을'list'보다는'vector'에 대해 생각했지만'T *'를 포함 할 수도있다. , 그리고 모든 포인터가 같은 크기가 아닙니다 ... 좋아요. 어떻게 멤버 함수의 컨테이너를 만들 었는지 모르겠지만 ... – BoBTFish

+0

@BoBTFish - 모든 포인터는 같은 크기입니다. –

답변

8

입니다.

표준은 내가 알고있는 한 list<T> 개체의 크기에 대한 보증을 제공하지 않습니다. 여전히 다른 보증이 있습니다.


은 우리가 몇 가지 정체를 폭로하자

표준 C++ 라이브러리는 '최적화'를 std::list<T> 자체에 T 인스턴스의 일부를 바꾸어 std::list 유형하려고합니다. 그건 나에게 나쁜 생각 인 것 같고 표준에 의해 요구되는 '일정한 시간'요구 사항을 깨뜨릴 수 있습니다.

O (5)가 O (1)이므로이 수를 한정하는 한 어떤 식 으로든 '일정 시간'요구 사항을 위반하지 않습니다. 그러나 splice 작업 중에 노드는으로 이동하지 않고 한 목록에서 다른 목록으로 이동해야합니다 ().따라서 로컬 저장이 금지됩니다.

다른 유형의 특수화를 사용하여 일부 유형의 경우 라이브러리 특수화가 std::list<T> 인 표준 C++입니다.

이미 로컬 스토리지의 가능성을 배제하기 때문에, 그 자체로베이스std::list<T>임의의 다른 변형을 상상하기 힘들다.


그리고 우리가 중요한 일에 대해 걱정하자 할당 자 :

std::list<T>에 의해 할당 된 메모리가 두 번째 템플릿 인수에 의해 제공됩니다. 대부분의 할당 자 (기본값 인 std::allocator<T> 포함)는 간단한 포인터 유형을 사용합니다 : T* ... 그러나 할당자는이 유형을 자유롭게 변경할 수 있습니다.

따라서 allocator 매개 변수 (더 정확하게는 포인터 유형)를 변경하면 본인이 본 모든 구현에서 std::list 컨테이너의 크기가 자연스럽게 변경됩니다.

할당 자 자체는 일부 유형에 대해 특수화 될 수 있지만 리바 인 마술은 달성하기가 조금 더 어렵다는 점에 유의하십시오.

+0

할당자가 발자국에 어떻게 영향을 줄 수 있는지 구체적으로 생각하면 +1. 아주 좋아. – Jon

4

C++ 11 표준 (컨테이너)의 23 장에서는 크기에 대해 아무 것도 말하지 않기 때문에 기술적으로 크기가 일정하다고 가정 할 수 없습니다. 구현자는 (이론 상으로는) 발자국에 영향을 미치는 방식으로 특정 프리미티브 용 컨테이너를 전문화 할 수 있습니다.

실제로는 sizeof(list<T>) == sizeof(list<int>)이라는 고정 어설 션을 사용하고 sizeof(list<int>)을 "고정"크기로 사용할 수 있습니다. 컴파일 타임 오류가 발생할 수있는 최악의 경우입니다.

0

std::list<T>을 사용하는 클래스의 고정 크기 슬라이스 할당자는 목록 크기에 고정 크기 슬라이스 할당 자도 사용하지 않는 한 목록 헤더보다 목록 항목에 더 많은 할당이있을 것입니다.

이제 할당자인 두 번째 템플릿 인수를 사용하여 자신의 고정 크기 슬라이스 할당자를 목록에 제공 할 수 있습니다. 그러나 비틀어 짐이 있습니다. 슬라이스가 얼마나 커야할지 모릅니다. A list<T>allocator<T>을 받아들입니다. 그러나 실제로 필요한 것은 allocator<U>입니다. 여기서 U는 이전/다음 포인터와 T를 포함하는 구조입니다.이 코드를 얻으려면 메서드를 호출하고 template <typename T> template <typename T> allocator<U> allocator<T>::rebind<U>()이라는 서명이 있어야합니다.

실제로 한 번 해보았으므로 여러 조각 크기의 할당 자 컬렉션을 보유하는 객체를 만드는 것이 었습니다. 할당 자 자체는 이것에 대한 공유 포인터와 그것의 인수의 크기에 대한 할당 자에 대한 공유 포인터를 가지고있다. 그리고 리바 인드 할 때 컬렉션에서 적절한 할당자를 꺼 냈고 존재하지 않으면 할당자를 만들었습니다. 이렇게하면 부작용으로 목록 할당을 해결할 수 있습니다. 하나 이상의 크기가있을 경우 각각에 대해 별도의 풀이 생성되므로 목록 할당을 해결합니다. 그리고 물체가 크지 않기 때문에 크기가 다양 할 것 같지 않습니다.

+0

목록은 슬라이스 할당 자 자체에서 사용되므로 직접 할당해야합니다. 그러나'std :: list '자체는 슬라이스 할당자를 사용하면 이익을 얻을만큼 충분히 작아야합니다. –