Por que string::compare
retorna um em int
vez de um tipo menor como short
ou char
? Meu entendimento é que esse método retorna apenas -1, 0 ou 1.
Segunda parte, se eu fosse projetar um método de comparação que compare dois objetos do tipo Foo
e quisesse apenas retornar -1, 0 ou 1, usar short
ou char
geralmente seria uma boa ideia?
EDIT: Fui corrigido, string::compare
não retorna -1, 0 ou 1, na verdade retorna um valor> 0, <0 ou 0. Obrigado por me manter na linha, pessoal.
Parece que a resposta é aproximadamente, não há razão para retornar um tipo menor do que int
porque os valores de retorno são "rvalues" e esses "rvalues" não se beneficiam de serem menores do que o tipo int (4 bytes). Além disso, muitas pessoas apontaram que os registros da maioria dos sistemas provavelmente serão de tamanho de int
qualquer maneira, uma vez que esses registros serão preenchidos independentemente de você dar a eles um valor de 1, 2 ou 4 bytes, não há nenhuma vantagem real em retornar um valor menor.
EDIT 2: Na verdade, parece que pode haver sobrecarga de processamento extra ao usar tipos de dados menores, como alinhamento, mascaramento, etc. O consenso geral é que os tipos de dados menores existem para economizar memória ao trabalhar com muitos dados, como no caso de uma matriz.
Aprendi algo hoje, obrigado novamente pessoal!
string::compare()
seu link afirma claramente que o valor de retorno é <0, 0 e> 0 -não- -1, 0 e 1.short
ou emchar
vez deint
? A maioria das arquiteturas vai armazenar o valor de retorno de uma função em um registro, e umint
caberá em um registro tão bem quanto umshort
ouchar
. E usarchar
para tipos numéricos é sempre uma má ideia, especialmente quando você precisa garantir que os valores assinados sejam tratados corretamente.char
seria uma má ideia, uma vez que a verificação do código do valor de retorno se for menor que zero irá falhar em plataformas ondechar
não está assinado.Respostas:
Em primeiro lugar, a especificação é que ele retornará um valor menor, igual ou maior que
0
, não necessariamente-1
ou1
. Em segundo lugar, os valores de retorno são rvalues, sujeitos à promoção integral, portanto, não faz sentido retornar nada menor.Em C ++ (como em C), cada expressão é um rvalue ou um lvalue. Historicamente, os termos referem-se ao fato de que lvalues aparecem à esquerda de uma atribuição, enquanto rvalues só podem aparecer à direita. Hoje, uma aproximação simples para tipos de não classe é que um lvalue tem um endereço na memória, um rvalue não. Portanto, você não pode obter o endereço de um rvalue, e os qualificadores cv (cuja condição "acesso") não se aplicam. Em termos de C ++, um rvalue que não tem tipo de classe é um valor puro, não um objeto. O valor de retorno de uma função é um rvalue, a menos que tenha um tipo de referência. (Tipos de não classe que cabem em um registro quase sempre serão retornados em um registro, por exemplo, ao invés de na memória.)
Para tipos de classe, os problemas são um pouco mais complexos, devido ao fato de que você pode chamar funções de membro em um rvalue. Isso significa que rvalues devem de fato ter endereços, para o
this
ponteiro, e podem ser cv-qualificados, visto que a cv-qualification desempenha um papel na resolução da sobrecarga. Finalmente, C ++ 11 introduz várias novas distinções, a fim de oferecer suporte a referências rvalue; estes também são principalmente aplicáveis aos tipos de classe.A promoção integral refere-se ao fato de que, quando tipos integrais menores do que um
int
são usados como rvalues em uma expressão, na maioria dos contextos, eles serão promovidos paraint
. Portanto, mesmo que eu tenha uma variável declaradashort a, b;
, na expressãoa + b
, ambosa
eb
são promovidos aint
antes de ocorrer a adição. Da mesma forma, se eu escrevera < 0
, a comparação é feita no valor dea
, convertido em umint
. Na prática, existem poucos casos em que isso faz diferença, pelo menos nas máquinas de complementos de 2 onde a aritmética de inteiros envolve (ou seja, todos, exceto alguns exóticos, hoje - acho que os mainframes da Unisys são as únicas exceções restantes). Ainda assim, mesmo nas máquinas mais comuns:deve dar resultados diferentes: o primeiro é equivalente a
sizeof( short )
, o segundosizeof( int )
(por causa da promoção integral).Essas duas questões são formalmente ortogonais; rvalues e lvalues não têm nada a ver com promoção integral. Exceto ... a promoção integral só se aplica a rvalues, e a maioria (mas não todos) dos casos em que você usaria um rvalue resultará em promoção integral. Por esse motivo, não há realmente nenhuma razão para retornar um valor numérico em algo menor que
int
. Há até uma razão muito boa para não devolvê-lo como um tipo de personagem. Operadores sobrecarregados, como<<
, geralmente se comportam de maneira diferente para os tipos de caracteres, então você só deseja retornar os caracteres como tipos de caracteres. (Você pode comparar a diferença:A diferença é que, no segundo caso, a adição fez com que ocorresse a promoção integral, o que resulta em uma sobrecarga diferente de
<<
ser escolhido.fonte
return values are rvalues, subject to integral promotion
em sua resposta.signed char
? Ele se comportaria da mesma forma que um assinadochar
ou seria de um tipo diferente?É intencional que não retorne -1, 0 ou 1.
Ele permite (observe que não é para strings, mas se aplica igualmente a strings)
o que é muito menos complicado do que:
que é o que você teria que fazer [ou algo nesse sentido] se você tivesse que retornar -1, 0 ou 1.
E também funciona para tipos mais complexos:
No caso da string, podemos fazer isso:
fonte
compare
função tem problemas com estouro que (felizmente) não se aplicam igualmente se levachar*
echar
é menor do queint
. Por exemplo, se*a
éMAX_INT
e*b
é,-1
então*a - *b
é UB, mas se a implementação escolher definir seu comportamento, o resultado quase certamente será negativo.length()
retorna asize_t
, que pode ser maior queint
...int é geralmente (ou seja, na maioria dos hardwares modernos) um inteiro do mesmo tamanho que o barramento do sistema e / ou os registradores da CPU, o que é chamado de palavra de máquina. Portanto, o int é normalmente transmitido mais rápido do que os tipos menores, porque não requer alinhamento, mascaramento e outras operações.
Os tipos menores existem principalmente para permitir a otimização do uso de RAM para arrays e estruturas. Na maioria dos casos, eles trocam alguns ciclos de CPU (na forma de operações de alinhamento) por um melhor uso de RAM.
A menos que você precise fazer com que seu valor de retorno seja um número com ou sem sinal de um tamanho centain (char, short ...), é melhor usar int, e é por isso que a biblioteca padrão faz isso.
fonte
É um C-ismo.
Quando C requer
compare
funções -type, elas sempre retornam umint
. C ++ apenas levou isso adiante (infelizmente).No entanto, retornar um
int
é realisticamente provavelmente a maneira mais rápida, pois geralmente é o tamanho dos registros do sistema em uso. (Deliberadamente vago.)fonte
short
echar
pode impor penalidades de desempenho, por exemplo,255+7
tem um valor diferente para achar
e,int
portanto, uma implementação correta não pode necessariamente simplesmente armazenar achar
onde umint
pode ir sem cuidar de manipular sua semântica. Os compiladores não necessariamente otimizarão a ineficiência que isso impõe.O método não retorna realmente um inteiro no conjunto
{ -1, 0, 1 }
; na verdade, pode ser qualquer valor integral.Por quê? A principal razão que consigo pensar é que esse
int
é o valor de "tamanho natural" da arquitetura; operações em valores desse tamanho são normalmente pelo menos tão rápidas (e em muitos casos mais rápidas) do que operações em valores menores ou maiores. Portanto, este é um caso de permitir a implementação folga suficiente para usar o que for mais rápido.fonte
Seria uma boa ideia. A melhor maneira seria retornar um bool (se quiser apenas comparar se for igual) ou enum (para obter mais informações):
fonte
Suponha que algumas pessoas estejam mudando um código de C para C ++. Eles decidiram substituir
strcmp
porstring::compare
.Desde que
strcmp
retornaint
, é mais fácilstring::compare
devolverint
, como um presente.fonte
Provavelmente para fazer funcionar mais como
strcmp
aquele que também tem esse conjunto de valores de retorno . Se você quisesse portar código, provavelmente seria mais intuitivo ter substitutos que se separassem o mais próximo possível.Além disso, o valor de retorno não é apenas
-1
,0
ou ,1
mas<0
,0
ou>0
.Além disso, conforme mencionado, uma vez que o retorno está sujeito a promoção integral , não faz sentido diminuí-lo.
fonte
porque um valor de retorno booleano só pode ter dois valores possíveis (verdadeiro, falso) e uma função de comparação pode retornar três valores possíveis (menor que, igual, maior que).
Atualizar
Embora seja certamente possível retornar um short assinado, se você realmente quiser implementar sua própria função de comparação, poderá retornar um valor nibble ou struct com dois booleanos.
fonte
short
echar
como alternativas paraint
.