Według cppreference.com size_t
jest zdefiniowany w kilku nagłówkach, a mianowicie
<cstddef>
<cstdio>
<cstring>
<ctime>
A od C ++ 11 również w
<cstdlib>
<cwchar>
Przede wszystkim zastanawiam się, dlaczego tak jest. Czy nie jest to sprzeczne z zasadą DRY ? Jednak moje pytanie brzmi:
Który z powyższych nagłówków powinienem dołączyć, aby użyć size_t
? Czy to w ogóle ma znaczenie?
<cstddef>
dostd::size_t
std::size_t
, a OP nie zalecał używania starszych funkcji C, po prostu obserwując cytat o tym, że dzielą krój pisma. Wątpię, czy ktoś czytający ten wątek zostałby z tego powodu wprowadzony w błąd i użyłby starszych typów / funkcji, ale jeśli chcesz mieć pewność, że tego nie robią, to w porządku!Odpowiedzi:
Zakładając, że chciałem zminimalizować funkcje i typy, które importowałem, wybrałbym,
cstddef
ponieważ nie deklaruje żadnych funkcji i deklaruje tylko 6 typów. Inni koncentrują się na określonych domenach (ciągach znaków, czasie, we / wy), które mogą nie mieć dla Ciebie znaczenia.Zauważ, że
cstddef
tylko gwarantuje zdefiniowaniestd::size_t
, to znaczy definiowaniesize_t
w przestrzeni nazwstd
, chociaż może dostarczyć tę nazwę również w globalnej przestrzeni nazw (w rzeczywistości, zwykłysize_t
).W przeciwieństwie do tego
stddef.h
(który jest również nagłówkiem dostępnym w C) gwarantuje zdefiniowaniesize_t
w globalnej przestrzeni nazw, a także może udostępniaćstd::size_t
.źródło
size_t
fromcstddef
jest taki sam i zawsze będzie taki sam jak inne? Wygląda na to, że powinien istnieć wspólny plik nagłówkowy z typowymi definicjami, takimi jaksize_t
...cstddef
.<cstddef>
lub wszystkie mogą zawierać jakiś wewnętrzny nagłówek, który właśnie definiujesize_t
.csttddef
w odpowiedzi jest literówka? Możecstddef
ma na myśli?W rzeczywistości streszczenie (zawarte w standardzie C ++) kilku nagłówków w szczególności obejmuje,
size_t
a także dalsze nagłówki definiują typsize_t
(w oparciu o standard C, ponieważ<cX>
nagłówki to tylko<X.h>
nagłówki ISO C ze zauważonymi zmianami, których usunięciesize_t
nie jest wskazane).C średnia ++ jednak odnosi się
<cstddef>
do zdefiniowaniastd::size_t
Dlatego i ze względu na fakt, że
<cstddef>
wprowadza tylko typy, a nie funkcje, trzymałbym się tego nagłówka, abystd::size_t
udostępnić.Zwróć uwagę na kilka rzeczy:
Typ
std::size_t
można uzyskać za pomocądecltype
bez nagłówkaJeśli planujesz wprowadzić typedef w kodzie i tak (tzn bo piszesz pojemnik i chcą zapewnić
size_type
typedef) można korzystać z globalnychsizeof
,sizeof...
czyalignof
operatorom określić typ bez żadnych nagłówków tym w ogóle od theose operatorzy powrócićstd::size_t
za standardowej rozdzielczości i możeszdecltype
na nich użyć :using size_type = decltype(alignof(char));
std::size_t
nie jest per se globalnie widoczny, chociaż funkcje zstd::size_t
argumentami są.Niejawnie zadeklarowane globalne funkcje alokacji i zwalniania alokacji
void* operator new(std::size_t); void* operator new[](std::size_t); void operator delete(void*); void operator delete[](void*);
NIE wprowadzaj
size_t
,std
anistd::size_t
iUżytkownik nie może przedefiniować,
std::size_t
chociaż możliwe jest posiadanie wielu typów definicji odwołujących się do tego samego typu w tej samej przestrzeni nazw.Chociaż występowanie wielu definicji
size_t
wewnątrzstd
jest całkowicie poprawne zgodnie z 7.1.3 / 3 , nie jest dozwolone dodawanie żadnych deklaracjinamespace std
zgodnie z 17.6.4.2.1 / 1 :Dodanie właściwej definicji typu for
size_t
do przestrzeni nazw nie narusza 7.1.3, ale narusza 17.6.4.2.1 i prowadzi do niezdefiniowanego zachowania.Wyjaśnienie: staraj się nie błędnie interpretować 7.1.3 i nie dodawaj deklaracji ani definicji do
std
(z wyjątkiem kilku przypadków specjalizacji szablonów, w których typedef nie jest specjalizacją szablonu). Rozszerzenienamespace std
źródło
std
jest nieprawidłowe, ponieważ zduplikowane czcionki są nielegalne. Oświadczam, że jest to nielegalne, ponieważ po prostu nie można dodawać do nich definicjinamespace std
- bez względu na to, czy byłyby one legalne.Wszystkie standardowe pliki nagłówkowe bibliotek mają tę samą definicję; nie ma znaczenia, który z nich umieścisz we własnym kodzie. Na moim komputerze mam następującą deklarację w formacie
_stddef.h
. Ten plik jest dołączany do każdego wymienionego pliku./* 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
źródło
size_t
w pierwszej kolejności?size_t
. Możesz zdefiniować to bardziej przenośnie jakousing size_t = decltype( sizeof( 42 ) )
. Ale nie ma takiej potrzeby, ponieważ<stddef.h>
ma prawie zerowy koszt.Możesz obejść się bez nagłówka:
using size_t = decltype(sizeof(int)); using size_t = decltype(sizeof 1); // The shortest is my favourite. using size_t = decltype(sizeof "anything");
Dzieje się tak, ponieważ standard C ++ wymaga:
Innymi słowy, norma wymaga:
static_assert(std::is_same<decltype(sizeof(int)), std::size_t>::value, "This never fails.");
Zauważ również, że jest całkowicie w porządku, aby uczynić tę
typedef
deklarację w globalnej istd
przestrzeni nazw, o ile pasuje ona do wszystkich innychtypedef
deklaracji o tej samej nazwie typu (w przypadku niezgodnych deklaracji jest generowany błąd kompilatora).To dlatego, że:
§7.1.3.1 Nazwa typedef-name nie wprowadza nowego typu, tak jak deklaracja klasy (9.1) lub deklaracja wyliczenia.
§7.1.3.3 W podanym zakresie nieklasowym
typedef
specyfikator może być użyty do przedefiniowania nazwy dowolnego typu zadeklarowanego w tym zakresie w celu odniesienia się do typu, do którego już się odnosi.Sceptykom, którzy twierdzą, że jest to dodanie nowego typu do przestrzeni nazw
std
, a takie działanie jest wprost zabronione przez standard, a to jest UB i to wszystko; Muszę powiedzieć, że takie podejście sprowadza się do ignorowania i zaprzeczania głębszemu zrozumieniu podstawowych kwestii.Standard zabrania dodawania nowych deklaracji i definicji do przestrzeni nazw,
std
ponieważ w ten sposób użytkownik może narobić bałaganu w bibliotece standardowej i odstrzelić sobie całą nogę. Standardowym autorom łatwiej było pozwolić użytkownikowi wyspecjalizować się w kilku konkretnych rzeczach i zakazać robienia czegokolwiek innego na miarę, zamiast blokować każdą rzecz, której użytkownik nie powinien robić i ryzykować, że przegapi coś ważnego (i tę nogę). Zrobili to w przeszłości, gdy wymagali, aby żaden standardowy kontener nie był tworzony z niekompletnym typem, podczas gdy w rzeczywistości niektóre kontenery mogą to zrobić (zobacz The Standard Librarian: Containers of Incomplete Types, Matthew H. Austern ):Biorąc pod uwagę, że zasady języka wymagają,
std::size_t
aby być dokładniedecltype(sizeof(int))
, robienienamespace std { using size_t = decltype(sizeof(int)); }
jest jedną z tych rzeczy, które niczego nie psują.Przed C ++ 11 nie było,
decltype
a zatem nie ma możliwości zadeklarowania typusizeof
wyniku w jednej prostej instrukcji bez angażowania dużej liczby szablonów.size_t
aliasy różnych typów na różnych architekturach docelowych, jednak nie byłoby eleganckim rozwiązaniem dodanie nowego typu wbudowanego tylko dla wyniku działania programusizeof
i nie ma standardowych wbudowanych definicji typów. Stąd najbardziej przenośnym rozwiązaniem w tamtym czasie było umieszczeniesize_t
aliasu typu w jakimś określonym nagłówku i udokumentowanie tego.W C ++ 11 jest teraz sposób na zapisanie tego dokładnego wymagania standardu jako jednej prostej deklaracji.
źródło
size_t
!” Minutę później Mary powiedziała: „OMG! Istnieje 7 definicjisize_t
wszystkich standardowych nagłówków bibliotek i nagłówek projektu, który Tom edytuje! Prawdopodobnie jest ich więcej w bibliotekach innych firm!” xkcd.com/927size_t
, nie odpowiada to prawdziwemu pytaniu PO: to tak, jakbym zapytał o nagłówek, w którymFILE
jest zadeklarowany, i sugerowałbyś napisanie własnego.