`size_t`에 어떤 헤더를 포함해야합니까?


98

cppreference.com 에 따르면 size_t여러 헤더, 즉

<cstddef>
<cstdio>
<cstring>
<ctime>

그리고 C ++ 11부터

<cstdlib>
<cwchar> 

우선 왜 이것이 사실인지 궁금합니다. 이것은 DRY 원칙 에 위배되지 않습니까? 그러나 내 질문은 다음과 같습니다.

위의 헤더 중 어떤 것을 사용하려면 포함해야 size_t합니까? 전혀 중요합니까?


2
해당 헤더 파일을 열고 정의를 찾으십시오.
i486

35
@ i486-부서지기 쉬운 비 휴대용 코드를 작성하는 좋은 방법입니다!
Sean

3
@PanagiotisKanavos C ++ 표준 라이브러리의 일부이며 아마도 '진정한 C ++'헤더에서 중복되지 않을 것입니다. 당신의 요점은 정확히 무엇입니까?
underscore_d

14
난 항상 사용 <cstddef>을 위해std::size_t
Boiethios

4
@PanagiotisKanavos 물론, 일반적으로 좋은 조언이지만,이 경우에는 관련성이없는 것 같습니다 std::size_t. 이 스레드를 읽는 사람이 이로 인해 레거시 유형 / 함수를 사용하도록 오해 당할 것 같지는 않지만 그렇지 않은지 확인하고 싶다면 충분히 공정합니다!
underscore_d

답변:


94

내가 가져온 함수와 유형을 최소화하고 싶다고 가정하면 함수를 cstddef선언하지 않고 6 유형 만 선언하므로 함께 갈 것입니다 . 다른 것들은 당신에게 중요하지 않은 특정 도메인 (문자열, 시간, IO)에 초점을 맞 춥니 다.

참고 cstddef만 정의하는 보장 std::size_t정의이며, size_t네임 스페이스 std가 있지만, 전역 네임 스페이스 (효과적으로, 일반에이 이름을 제공합니다 size_t).

반면에 stddef.h(도 C 가능 헤더 임) 정의 보장 size_t글로벌 네임 스페이스하고 있다 또한 제공한다 std::size_t.


3
size_tfrom cstddef이 동일하고 항상 다른 사람과 동일 하다는 보장이 있습니까? 같은 일반적인 정의가 공통 헤더 파일이 있어야처럼 보인다 size_t...
SnakeDoc

1
@SnakeDoc과 마술처럼 여기에 또 다른 대답은 '내부'헤더를 통해 정확히 발생하는 것을 이미 관찰했습니다.
underscore_d

5
@SnakeDoc 예, 그 헤더는 cstddef.
user253751

2
@SnakeDoc, 누가 자신을 정의한다고? 모든 표준은 해당 헤더를 포함시킨 후 정의 될 것이라고 말하며 모두 재정의해야한다고 말하는 것은 아닙니다. 모두 포함 <cstddef>할 수도 있고 정의하는 내부 헤더를 모두 포함 할 수도 size_t있습니다.
조나단 Wakely

1
는 IS csttddef대답에 오타? 어쩌면 cstddef의미입니까?
Erik Sjölund

47

실제로 여러 헤더의 시놉시스 (C ++ 표준에 포함됨)에는 size_t유형을 정의 할뿐만 아니라 추가 헤더가 명시 적으로 포함 됩니다 size_t( <cX>헤더는 <X.h>제거 size_t가 표시되지 않은 변경 사항 이있는 ISO C 헤더 일 뿐이 므로 C 표준을 기반으로 함).

C ++ 표준은 그러나, 을 의미 <cstddef>의 정의std::size_t

  • 에서 18.2 유형 ,
  • 에서 SIZEOF 5.3.3 ,
  • 에서 3.7.4.2 할당 해제 기능 (이 18.2 지칭) 및
  • 에서 3.7.4.1 할당 함수 (18.2도를 말한다).

따라서 <cstddef>유형 만 소개하고 기능은 제공하지 않기 때문에이 헤더를 사용하여 std::size_t사용할 수 있도록 합니다.


몇 가지 사항에 유의하십시오.

  1. 의 유형은 헤더를 포함하지 않고 std::size_t사용하여 얻을 수 있습니다.decltype

    넌 계획 어쨌든 코드에서 타입 정의를 소개하는 경우 (즉, 당신은 컨테이너를 작성하고 제공하기 원하기 때문에 size_type형식 정의를) 전역 사용할 수 있습니다 sizeof, sizeof...또는 alignoftheose 사업자가 반환 이후 전혀 헤더를 포함하지 않고 당신의 유형을 정의하는 연산자를 std::size_t당 표준 정의이며 다음과 같이 사용할 수 decltype있습니다.

    using size_type = decltype(alignof(char));
    
  2. std::size_tstd::size_t인수가있는 함수는 있지만 그 자체로는 전역 적으로 표시되지 않습니다 .

    암시 적으로 선언 된 전역 할당 및 할당 해제 함수

    void* operator new(std::size_t);
    void* operator new[](std::size_t);
    void operator delete(void*);
    void operator delete[](void*);
    

    소개하지 마십시오 size_t, std또는 std::size_t

    적절한 헤더를 포함하여 이름이 선언되지 않는 한 참조 std하거나 std::size_t잘못된 형식입니다.

  3. std::size_t동일한 네임 스페이스에서 동일한 유형을 참조하는 여러 typedef를 가질 수 있지만 사용자는 재정의 할 수 없습니다 .

    의 여러 정의의 발생,하지만 size_t내가 std당 완벽하게 유효 7.1.3 / 3 , 어떤 선언을 추가 할 수 없습니다 namespace std와 같은 당 17.6.4.2.1 / 1 :

    C ++ 프로그램의 동작은 별도로 지정하지 않는 한 네임 스페이스 std 또는 네임 스페이스 std 내의 네임 스페이스에 선언 또는 정의를 추가하는 경우 정의되지 않습니다.

    size_t네임 스페이스에 대한 적절한 typedef를 추가하는 것은 7.1.3을 위반하지 않지만 17.6.4.2.1을 위반 하고 정의되지 않은 동작으로 이어집니다.

    설명 : 7.1.3 을 잘못 해석 하지 말고 선언이나 정의를 추가하지 마십시오 std(typedef가 템플릿 전문화가 아닌 몇 가지 템플릿 전문화 사례 제외). 확장namespace std


1
중복 typedef가 새 유형을 도입하지 않는다는 사실을 놓칩니다. 완벽하게 유효한 중복 typedef를 추가 할뿐입니다.
Maxim Egorushkin 2011

@MaximEgorushkin : std중복 typedef가 불법이기 때문에 재정의 typedef를 추가하는 것이 유효 하지 않다고 주장하지 않습니다 . namespace std합법적인지 여부에 관계없이 정의를 추가 할 수 없기 때문에 불법이라고 말합니다 .
Pixelchemist 2016

이 모든 표준 인용문에서 우리가 아는 모든 것을 고려할 때 잠재적으로 깨질 수있는 것은 무엇입니까?
Maxim Egorushkin

12
@MaximEgorushkin : 뭐든지. 그것이 정의되지 않은 행동에 관한 것이지, 그렇지 않습니까? 작동 할 있는 지점 또는 임의의 컴파일러에서 중단 되지 않는 지점 은 표준에 따라 정의 된 프로그램의 동작을 만들지 않습니다. 또는 'fredoverflow'가 여기에 멋지게 표현한 것처럼 "C ++ 표준은 유일한 투표 기간을 가지고 있습니다."
Pixelchemist

당신의 비판적 사고를 활용하시기 바랍니다. 잠재적으로 깨질 수있는 것은 무엇입니까?
Maxim Egorushkin 2012

9

모든 표준 라이브러리 헤더 파일은 동일한 정의를 갖습니다. 자신의 코드에 어떤 것을 포함시키는지는 중요하지 않습니다. 내 컴퓨터에는 _stddef.h. 이 파일은 나열한 모든 파일에 포함되어 있습니다.

/*
   Define the size_t type in the std namespace if in C++ or globally if in C.
   If we're in C++, make the _SIZE_T macro expand to std::size_t
*/

#if !defined(_SIZE_T) && !defined(_SIZE_T_DEFINED)
#  define _SIZE_T_DEFINED
#if defined(_WIN64)
   typedef unsigned __int64 size_t;
#else
   typedef unsigned int size_t;
#endif
#  if defined(__cplusplus)
#    define _SIZE_T std::size_t
#  else
#    define _SIZE_T size_t
#  endif
#endif

2
확실하지는 않지만 컴파일 시간에 중요하다고 생각합니다.
idclev 463035818

이 특정 질문에는 @ tobi303이 아닙니다. 예, 필요 이상으로 더 큰 헤더를 추가 할 수 있지만 이미 C ++ 프로젝트에 C 헤더를 추가했습니다. size_t애초에 왜 필요한 가요?
Panagiotis Kanavos 2016

을 정의하기 위해 OS 매크로 스니핑을 사용하는 것은 좋은 생각이 아닙니다 size_t. 더 이식 가능하게 using size_t = decltype( sizeof( 42 ) ). 그러나 <stddef.h>거의 비용이 들지 않기 때문에 필요가 없습니다 .
건배와 hth. - 알프

4

헤더 없이도 할 수 있습니다.

using size_t = decltype(sizeof(int));
using size_t = decltype(sizeof 1); //  The shortest is my favourite.
using size_t = decltype(sizeof "anything");

이는 C ++ 표준에 다음이 필요하기 때문입니다.

sizeof및 의 결과는 sizeof...유형 상수입니다 std::size_t. [참고 : std::size_t표준 헤더 <cstddef>(18.2)에 정의되어 있습니다. — 끝 참고]

즉, 표준은 다음을 요구합니다.

static_assert(std::is_same<decltype(sizeof(int)), std::size_t>::value,
              "This never fails.");

또한 동일한 typedef-name 의 다른 모든 선언 과 일치 typedef하는 한 전역 및 std네임 스페이스 에서이 선언 을 만드는 것이 완벽합니다.typedef (일치하지 않는 선언에서 컴파일러 오류가 발생 함).

이 때문입니다:

  • §7.1.3.1 typedef-name 은 클래스 선언 (9.1)이나 열거 형 선언처럼 새로운 유형을 도입하지 않습니다.

  • §7.1.3.3 지정된 클래스가 아닌 범위에서 typedef지정자를 사용하여 해당 범위에서 선언 된 모든 형식의 이름을 이미 참조하는 형식을 참조하도록 재정의 할 수 있습니다.


회의론자들에게 이것이 네임 스페이스에 새로운 유형의 추가를 구성한다고 말합니다. std 하고 그러한 행위는 표준에 의해 명시 적으로 금지되고 있으며 이것이 UB이고 그게 전부 ; 나는 이러한 태도가 근본적인 문제에 대한 더 깊은 이해를 무시하고 부정하는 것이라고 말해야합니다.

표준은 네임 스페이스에 새로운 선언과 정의를 추가하는 것을 금지합니다. std그렇게하면 사용자가 표준 라이브러리를 엉망으로 만들고 그의 다리 전체를 쏠 수 있기 때문입니다. 표준 작가의 경우, 사용자가하지 말아야 할 모든 일을 금지하고 중요한 일 (그리고 그 다리)을 놓칠 위험이있는 것보다 사용자가 몇 가지 특정 일을 전문화하고 좋은 조치를 위해 다른 일을하는 것을 금지하는 것이 더 쉬웠습니다. 과거에는 표준 컨테이너가 불완전한 유형으로 인스턴스화되지 않도록 요구할 때이를 수행했지만 실제로 일부 컨테이너는 잘 수행 할 수 있습니다 ( Matthew H. Austern의 The Standard Librarian : Containers of Incomplete Types 참조 ).

... 결국 모든 것이 너무 어둡고 너무 잘 이해되지 않는 것처럼 보였습니다. 표준화위원회는 STL 컨테이너가 불완전한 유형으로 작동해서는 안된다고 말하는 것 외에는 선택의 여지가 없다고 생각했습니다. 좋은 측정을 위해 우리는이 금지를 나머지 표준 라이브러리에도 적용했습니다.

... 돌이켜 보면 이제 기술이 더 잘 이해되었으므로 그 결정은 여전히 ​​기본적으로 옳은 것 같습니다. 예, 어떤 경우에는 일부 표준 컨테이너를 구현하여 불완전한 유형으로 인스턴스화 할 수 있지만 다른 경우에는 어렵거나 불가능하다는 것도 분명합니다. 을 사용하여 시도한 첫 번째 테스트가 std::vector쉬운 경우 중 하나 일 가능성이 큽니다.

언어 규칙 std::size_t이 정확히되어야 한다는 점을 감안할 때 decltype(sizeof(int)),하는 namespace std { using size_t = decltype(sizeof(int)); }것은 아무것도 깨뜨리지 않는 일 중 하나입니다.

C ++ 11 이전에는 많은 템플릿을 사용하지 않고는 하나의 간단한 명령문에서 결과 decltype유형을 선언 할 방법이 없었습니다 sizeof. size_t다른 대상 아키텍처에서 다른 유형을 별칭으로 지정하지만의 결과에 대해서만 새로운 내장 유형을 추가하는 것은 우아한 솔루션 sizeof이 아니며 표준 내장 typedef가 없습니다. 따라서 당시 가장 이식 가능한 솔루션은 size_t특정 헤더와 문서 에 유형 별칭 을 넣는 것이 었습니다 .

C ++ 11에는 표준의 정확한 요구 사항을 하나의 간단한 선언으로 기록하는 방법이 있습니다.


6
@Sean 작성한 내용이 의미가 없습니다.
Maxim Egorushkin

15
@MaximEgorushkin 그들 중 절반은이 코드를 이해하지 못했습니다. 완벽하게 작동합니다. 그러나 나는 이런 방식을 좋아하지 않는다. imo는 헤더를 포함하고 표준이 그것을 정의하도록하는 것이 더 낫다.
Boiethios

9
여러분, 최소한 완벽하게 정답을 내리기 전에 effing 언어를 배우십시오.
Frédéric Hamidi 2011

11
Tom은 "같은 것을 정의하는 6 개의 표준 라이브러리 헤더가 있습니다! 그건 말도 안 돼요! 우리는 단 하나의 정의 만 필요합니다 size_t!" 1 분 후 Mary는 "OMG! size_t표준 라이브러리 헤더와 Tom이 편집중인 프로젝트 헤더에 대한 7 개의 정의가 있습니다! 타사 라이브러리에 더 많은 것이있을 것입니다!" xkcd.com/927

6
이것이 가능한 정의 size_t이지만 이것은 OP의 실제 질문에 대답하지 않습니다. 마치 내가 FILE선언 된 헤더를 요청 하고 내 자신의 것을 작성하도록 제안하는 것과 같습니다.
edmz 2011
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.