De acordo com cppreference.com size_t
é definido em vários cabeçalhos, nomeadamente
<cstddef>
<cstdio>
<cstring>
<ctime>
E, desde C ++ 11, também em
<cstdlib>
<cwchar>
Em primeiro lugar, me pergunto por que isso acontece. Isso não está em contradição com o princípio DRY ? No entanto, minha pergunta é:
Qual dos cabeçalhos acima devo incluir para usar size_t
? Isso tem alguma importância?
<cstddef>
parastd::size_t
std::size_t
e o OP não estava defendendo o uso de funções C legadas, apenas observando a citação sobre eles compartilharem o typedef. Duvido que alguém lendo este tópico seja induzido a usar tipos / funções legados por causa disso, mas se você quiser ter certeza de que não o fazem, então é justo!Respostas:
Supondo que eu quisesse minimizar as funções e os tipos que estava importando, eu usaria,
cstddef
pois ele não declara nenhuma função e declara apenas 6 tipos. Os outros focam em domínios específicos (strings, tempo, IO) que podem não importar para você.Observe que
cstddef
apenas garante definirstd::size_t
, ou seja, definirsize_t
no namespacestd
, embora possa fornecer esse nome também no namespace global (efetivamente, simplessize_t
).Em contraste,
stddef.h
(que também é um cabeçalho disponível em C) garante a definiçãosize_t
no namespace global e também pode fornecerstd::size_t
.fonte
size_t
decstddef
é o mesmo e sempre será o mesmo que os outros? Parece que deveria haver um arquivo de cabeçalho comum com definições comuns comosize_t
...cstddef
.<cstddef>
ou podem incluir algum cabeçalho interno que apenas definesize_t
.csttddef
resposta é um erro de digitação? Talvezcstddef
se queira dizer?Na verdade, a sinopse (incluída no padrão C ++) de vários cabeçalhos inclui especificamente
size_t
, bem como outros cabeçalhos definem o tiposize_t
(com base no padrão C, pois os<cX>
cabeçalhos são apenas<X.h>
cabeçalhos ISO C com alterações observadas onde a remoção desize_t
não é indicada).O padrão C ++, no entanto, refere-se à
<cstddef>
definição destd::size_t
Portanto, e devido ao fato de que
<cstddef>
introduz apenas tipos e nenhuma função, eu ficaria com este cabeçalho parastd::size_t
disponibilizá-lo.Observe algumas coisas:
O tipo de
std::size_t
pode ser obtidodecltype
sem incluir um cabeçalhoSe você está planejando para introduzir um typedef em seu código de qualquer maneira (ou seja, porque você escreve um recipiente e deseja fornecer um
size_type
typedef) você pode usar os globaissizeof
,sizeof...
oualignof
operadores para definir o seu tipo sem incluir quaisquer cabeçalhos em tudo desde theose operadores retornarstd::size_t
per definição padrão e você pode usardecltype
neles:std::size_t
não é per se globalmente visível, embora funções comstd::size_t
argumentos sejam.As funções de alocação e desalocação globais implicitamente declaradas
NÃO apresente
size_t
,std
oustd::size_t
eO usuário não pode redefinir,
std::size_t
embora seja possível ter vários typedefs referentes ao mesmo tipo no mesmo namespace.Embora a ocorrência de múltiplas definições de
size_t
dentrostd
seja perfeitamente válida conforme 7.1.3 / 3 , não é permitido adicionar quaisquer declaraçõesnamespace std
conforme 17.6.4.2.1 / 1 :Adicionar um typedef adequado para
size_t
ao namespace não viola 7.1.3, mas viola 17.6.4.2.1 e leva a um comportamento indefinido.Esclarecimento: Tente não interpretar mal 7.1.3 e não adicione declarações ou definições
std
(exceto alguns casos de especialização de template onde um typedef não é uma especialização de template). Estendendo onamespace std
fonte
std
seja inválido porque typedefs duplicados são ilegais. Afirmo que é ilegal porque você simplesmente não pode adicionar definições anamespace std
- não importa se elas seriam legais.Todos os arquivos de cabeçalho de biblioteca padrão têm a mesma definição; não importa qual você incluir em seu próprio código. No meu computador, tenho a seguinte declaração em
_stddef.h
. Este arquivo está incluído em todos os arquivos listados.fonte
size_t
em primeiro lugar?size_t
. Você pode defini-lo de forma mais portátil comousing size_t = decltype( sizeof( 42 ) )
. Mas não há necessidade, pois<stddef.h>
tem custo quase zero.Você poderia fazer sem um cabeçalho:
Isso ocorre porque o padrão C ++ requer:
Em outras palavras, o padrão requer:
Observe também que é perfeitamente correto fazer essa
typedef
declaração no global e nostd
namespace, desde que corresponda a todas as outrastypedef
declarações do mesmo nome de typedef (um erro do compilador é emitido em declarações não correspondentes).Isto é porque:
§7.1.3.1 Um typedef-name não introduz um novo tipo da mesma forma que uma declaração de classe (9.1) ou declaração enum o faz.
§7.1.3.3 Em um determinado escopo de não classe, um
typedef
especificador pode ser usado para redefinir o nome de qualquer tipo declarado naquele escopo para se referir ao tipo ao qual ele já se refere.Para os céticos, dizendo que isso constitui uma adição de um novo tipo ao namespace
std
, e tal ato é explicitamente proibido pelo padrão, e isso é UB e isso é tudo; Devo dizer que essa atitude equivale a ignorar e negar uma compreensão mais profunda das questões subjacentes.O padrão proíbe a adição de novas declarações e definições no namespace
std
porque, ao fazer isso, o usuário pode bagunçar a biblioteca padrão e atirar em toda a sua perna. Para os escritores padrão, era mais fácil deixar o usuário se especializar em algumas coisas específicas e banir qualquer outra coisa para uma boa medida, ao invés de banir cada coisa que o usuário não deveria fazer e correr o risco de perder algo importante (e aquela perna). Eles fizeram isso no passado ao exigir que nenhum contêiner padrão seja instanciado com um tipo incompleto, enquanto na verdade alguns contêineres bem poderiam fazer (consulte The Standard Librarian: Containers of Incomplete Types de Matthew H. Austern ):Dado que as regras da linguagem exigem
std::size_t
ser exatasdecltype(sizeof(int))
, fazernamespace std { using size_t = decltype(sizeof(int)); }
é uma daquelas coisas que não quebra nada.Antes do C ++ 11, não havia
decltype
e, portanto, nenhuma maneira de declarar o tipo desizeof
resultado em uma instrução simples sem envolver uma grande quantidade de modelos.size_t
aliases diferentes tipos em diferentes arquiteturas de destino, no entanto, não seria uma solução elegante adicionar um novo tipo integrado apenas pelo resultado desizeof
, e não há typedefs integrados padrão. Conseqüentemente, a solução mais portátil na época era colocarsize_t
alias de tipo em algum cabeçalho específico e documentá-lo.No C ++ 11 agora existe uma maneira de escrever esse requisito exato do padrão como uma declaração simples.
fonte
size_t
!" Um minuto depois, Mary disse: "Meu Deus! Existem 7 definições desize_t
cabeçalhos de biblioteca padrão e um cabeçalho de projeto que Tom está editando! Provavelmente há mais nas bibliotecas de terceiros!" xkcd.com/927size_t
, isso não responde à verdadeira questão do OP: é como se eu perguntasse o cabeçalho ondeFILE
está declarado e você sugerisse escrever o meu próprio.