Menurut cppreference.com size_t
didefinisikan dalam beberapa header, yaitu
<cstddef>
<cstdio>
<cstring>
<ctime>
Dan, sejak C ++ 11, juga di
<cstdlib>
<cwchar>
Pertama-tama saya bertanya-tanya mengapa ini terjadi. Bukankah ini bertentangan dengan prinsip KERING ? Namun, pertanyaan saya adalah:
Manakah dari tajuk di atas yang harus saya sertakan untuk digunakan size_t
? Apakah itu penting?
<cstddef>
untukstd::size_t
std::size_t
, dan OP tidak menganjurkan penggunaan fungsi C lama, hanya mengamati kutipan tentang mereka yang membagikan typedef. Saya ragu siapa pun yang membaca utas ini akan disesatkan untuk menggunakan jenis / fungsi warisan karena ini, tetapi jika Anda ingin memastikan mereka tidak melakukannya, cukup adil!Jawaban:
Dengan asumsi saya ingin meminimalkan fungsi dan tipe yang saya impor, saya akan menggunakannya
cstddef
karena tidak mendeklarasikan fungsi apa pun dan hanya mendeklarasikan 6 jenis. Yang lain fokus pada domain tertentu (string, waktu, IO) yang mungkin tidak penting bagi Anda.Perhatikan bahwa
cstddef
hanya jaminan untuk mendefinisikanstd::size_t
, yaitu, menentukansize_t
dalam namespacestd
, meskipun mungkin memberikan nama ini juga di namespace global (efektif, biasasize_t
).Sebaliknya,
stddef.h
(yang juga merupakan header yang tersedia di C) jaminan untuk didefinisikansize_t
dalam namespace global, dan mungkin juga menyediakanstd::size_t
.sumber
size_t
fromcstddef
adalah sama dan akan selalu sama dengan yang lain? Sepertinya harus ada file header umum dengan definisi umum sepertisize_t
...cstddef
.<cstddef>
, atau semuanya dapat menyertakan beberapa header internal yang baru saja didefinisikansize_t
.csttddef
jawabannya salah ketik? Mungkincstddef
maksudnya?Faktanya, sinopsis (termasuk dalam standar C ++) dari beberapa header yang secara spesifik disertakan
size_t
serta header lebih lanjut menentukan jenisnyasize_t
(berdasarkan standar C karena<cX>
header hanyalah<X.h>
header ISO C dengan perubahan yang dicatat di mana penghapusansize_t
tidak diindikasikan).Standar C ++ bagaimanapun, mengacu
<cstddef>
pada definisistd::size_t
Oleh karena itu dan karena fakta bahwa
<cstddef>
hanya memperkenalkan tipe dan tidak ada fungsi, saya akan tetap menggunakan header ini untuk membuatnyastd::size_t
tersedia.Perhatikan beberapa hal:
Jenis
std::size_t
dapat diperoleh dengandecltype
tanpa menyertakan headerJika Anda berencana untuk memperkenalkan typedef dalam kode Anda (yaitu karena Anda menulis wadah dan ingin menyediakan
size_type
typedef) Anda dapat menggunakan globalsizeof
,sizeof...
ataualignof
operator untuk menentukan tipe Anda tanpa menyertakan header sama sekali karena operator theose kembalistd::size_t
per definisi standar dan Anda dapat menggunakannyadecltype
:using size_type = decltype(alignof(char));
std::size_t
tidak terlihat secara global meskipun fungsi denganstd::size_t
argumennya ada.Fungsi alokasi dan deallocation global yang dideklarasikan secara implisit
void* operator new(std::size_t); void* operator new[](std::size_t); void operator delete(void*); void operator delete[](void*);
JANGAN memperkenalkan
size_t
,std
ataustd::size_t
danPengguna tidak boleh mendefinisikan ulang
std::size_t
meskipun dimungkinkan untuk memiliki beberapa typedef yang merujuk ke tipe yang sama di namespace yang sama.Meskipun, terjadinya beberapa definisi di
size_t
dalamstd
benar-benar valid sesuai 7.1.3 / 3 , tidak diperbolehkan untuk menambahkan deklarasi apa punnamespace std
sesuai 17.6.4.2.1 / 1 :Menambahkan typedef yang tepat untuk
size_t
namespace tidak melanggar 7.1.3 tetapi melanggar 17.6.4.2.1 dan menyebabkan perilaku tidak terdefinisi.Klarifikasi: Cobalah untuk tidak salah menafsirkan 7.1.3 dan jangan menambahkan deklarasi atau definisi ke
std
(kecuali beberapa kasus spesialisasi template di mana typedef bukan spesialisasi template). Memperluasnamespace std
sumber
std
tidak valid karena typedef duplikat adalah ilegal. Saya menyatakan bahwa itu ilegal karena Anda tidak boleh menambahkan definisi kenamespace std
- tidak peduli apakah itu legal.Semua file header perpustakaan standar memiliki definisi yang sama; tidak masalah mana yang Anda masukkan dalam kode Anda sendiri. Di komputer saya, saya memiliki deklarasi berikut di
_stddef.h
. File ini disertakan oleh setiap file yang Anda daftarkan./* 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
sumber
size_t
?size_t
. Anda dapat mendefinisikannya dengan lebih portabel sebagaiusing size_t = decltype( sizeof( 42 ) )
. Tapi tidak perlu, karena<stddef.h>
biayanya hampir nol.Anda dapat melakukannya tanpa header:
using size_t = decltype(sizeof(int)); using size_t = decltype(sizeof 1); // The shortest is my favourite. using size_t = decltype(sizeof "anything");
Ini karena standar C ++ membutuhkan:
Dengan kata lain, standar tersebut mensyaratkan:
static_assert(std::is_same<decltype(sizeof(int)), std::size_t>::value, "This never fails.");
Perhatikan juga, bahwa tidak masalah untuk membuat
typedef
deklarasi ini di global dan distd
namespace, selamatypedef
deklarasi tersebut cocok dengan semua deklarasi lain dengan nama typedef yang sama (kesalahan kompiler dikeluarkan pada deklarasi yang tidak cocok).Hal ini karena:
§7.1.3.1 Nama typedef tidak memperkenalkan tipe baru seperti yang dilakukan deklarasi kelas (9.1) atau deklarasi enum.
§7.1.3.3 Dalam lingkup non-kelas tertentu, penentu
typedef
dapat digunakan untuk mendefinisikan kembali nama jenis apa pun yang dideklarasikan dalam lingkup itu untuk merujuk ke jenis yang telah dirujuk.Untuk para skeptis yang mengatakan bahwa ini merupakan penambahan tipe baru ke dalam namespace
std
, dan tindakan seperti itu secara eksplisit dilarang oleh standar, dan ini adalah UB dan itu saja; Saya harus mengatakan bahwa sikap ini berarti mengabaikan dan menyangkal pemahaman yang lebih dalam tentang masalah yang mendasarinya.Larangan standar menambahkan deklarasi dan definisi baru ke dalam namespace
std
karena dengan melakukan itu pengguna dapat mengacaukan perpustakaan standar dan menembak seluruh kakinya. Untuk penulis standar, lebih mudah untuk membiarkan pengguna mengkhususkan beberapa hal tertentu dan melarang melakukan hal lain untuk ukuran yang baik, daripada melarang setiap hal yang tidak boleh dilakukan pengguna dan berisiko kehilangan sesuatu yang penting (dan kaki itu). Mereka melakukannya di masa lalu ketika mensyaratkan bahwa tidak ada kontainer standar yang dibuat dengan tipe yang tidak lengkap, padahal beberapa kontainer dapat melakukannya dengan baik (lihat Pustakawan Standar: Kontainer Tipe Tidak Lengkap oleh Matthew H. Austern ):Mengingat bahwa aturan bahasa
std::size_t
harus tepatdecltype(sizeof(int))
, melakukannamespace std { using size_t = decltype(sizeof(int)); }
adalah salah satu hal yang tidak merusak apa pun.Sebelum C ++ 11 tidak ada
decltype
dan dengan demikian tidak ada cara untuk mendeklarasikan tipesizeof
hasil dalam satu pernyataan sederhana tanpa melibatkan banyak template.size_t
Alias tipe yang berbeda pada arsitektur target yang berbeda, bagaimanapun, itu tidak akan menjadi solusi yang elegan untuk menambahkan tipe built-in baru hanya untuk hasilsizeof
, dan tidak ada typedef bawaan standar. Oleh karena itu, solusi yang paling portabel saat itu adalah dengan meletakkansize_t
alias tipe di beberapa header dan dokumen tertentu itu.Di C ++ 11 sekarang ada cara untuk menuliskan persyaratan standar yang tepat sebagai satu deklarasi sederhana.
sumber
size_t
!" Satu menit kemudian, Mary berkata, "OMG! Ada 7 definisi darisize_t
seluruh header perpustakaan standar dan header proyek yang sedang diedit Tom! Mungkin ada lebih banyak lagi di perpustakaan pihak ketiga!" xkcd.com/927size_t
, ini tidak menjawab pertanyaan OP yang sebenarnya: seolah-olah saya meminta tajuk di manaFILE
dinyatakan dan Anda akan menyarankan untuk menulis tajuk saya sendiri.