Programing

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

lottogame 2020. 10. 17. 08:59
반응형

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


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

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

그리고 C ++ 11부터

<cstdlib>
<cwchar> 

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

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


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

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

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


실제로 여러 헤더의 시놉시스 (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


모든 표준 라이브러리 헤더 파일은 동일한 정의를 갖습니다. 자신의 코드에 어떤 것을 포함시키는지는 중요하지 않습니다. 내 컴퓨터에는 _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

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

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.");

Also note, that it is perfectly fine to make this typedef declaration in the global and in std namespace, as long as it matches all other typedef declarations of the same typedef-name (a compiler error is issued on non-matching declarations).

This is because:

  • §7.1.3.1 A typedef-name does not introduce a new type the way a class declaration (9.1) or enum declaration does.

  • §7.1.3.3 In a given non-class scope, a typedef specifier can be used to redefine the name of any type declared in that scope to refer to the type to which it already refers.


To sceptics saying that this constitutes an addition of a new type into namespace std, and such an act is explicitly prohibited by the standard, and this is UB and that is all there to it; I have to say that this attitude amounts to ignoring and denying deeper understanding of the underlying issues.

The standard bans adding new declarations and definitions into namespace std because by doing so the user may make a mess of the standard library and shoot his entire leg off. For the standard writers it was easier to let the user specialize a few specific things and ban doing anything else for good measure, rather than ban every single thing which the user should not do and risk missing something important (and that leg). They did it in the past when requiring that no standard container shall be instantiated with an incomplete type, while in fact some containers could well do (see The Standard Librarian: Containers of Incomplete Types by Matthew H. Austern):

... In the end, it all seemed too murky and too poorly understood; the standardization committee didn't think there was any choice except to say that STL containers aren't supposed to work with incomplete types. For good measure, we applied that prohibition to the rest of the standard library too.

... In retrospect, now that the technology is better understood, that decision still seems basically right. Yes, in some cases it's possible to implement some of the standard containers so that they can be instantiated with incomplete types — but it's also clear that in other cases it would be difficult or impossible. It was mostly chance that the first test we tried, using std::vector, happened to be one of the easy cases.

Given that the language rules require std::size_t to be exactly decltype(sizeof(int)), doing namespace std { using size_t = decltype(sizeof(int)); } is one of those things that do not break anything.

Prior to C++11 there was no decltype and thus no way to declare the type of sizeof result in one simple statement without getting a good deal of templates involved. size_t aliases different types on different target architectures, however, it would not be an elegant solution to add a new built-in type just for the result of sizeof, and there are no standard built-in typedefs. Hence, the most portable solution at the time was to put size_t type alias in some specific header and document that.

In C++11 there is now a way to write down that exact requirement of the standard as one simple declaration.

참고URL : https://stackoverflow.com/questions/36594569/which-header-should-i-include-for-size-t

반응형