Dlaczego string::compare
zwraca int
zamiast mniejszego typu, jak short
lub char
? Rozumiem, że ta metoda zwraca tylko -1, 0 lub 1.
Druga część, gdybym miał zaprojektować metodę porównania, która porównuje dwa obiekty typu Foo
i chciałbym zwrócić tylko -1, 0 lub 1, czy użycie short
lub char
ogólnie byłoby dobrym pomysłem?
EDYCJA: Zostałem poprawiony, string::compare
nie zwraca -1, 0 ani 1, w rzeczywistości zwraca wartość> 0, <0 lub 0. Dzięki za trzymanie mnie w kolejce.
Wygląda na to, że odpowiedź jest mniej więcej taka, że nie ma powodu, aby zwracać typ mniejszy niż int
dlatego, że zwracane wartości to „rvalues”, a te „rvalues” nie korzystają z tego, że są mniejsze niż typ int (4 bajty). Wiele osób wskazywało również, że rejestry większości systemów prawdopodobnie i tak będą miały rozmiar int
, ponieważ te rejestry będą wypełnione bez względu na to, czy dasz im wartość 1, 2 czy 4 bajty, nie ma realnej korzyści z zwracania wartości mniejsza wartość.
EDYCJA 2: W rzeczywistości wygląda na to, że przy użyciu mniejszych typów danych, takich jak wyrównanie, maskowanie itp., Może wystąpić dodatkowe obciążenie związane z przetwarzaniem. Ogólny konsensus jest taki, że mniejsze typy danych istnieją, aby oszczędzać pamięć podczas pracy z dużą ilością danych, jak w przypadek tablicy.
Nauczyłem się czegoś dzisiaj, jeszcze raz dziękuję chłopaki!
string::compare()
którejshort
lubchar
zamiastint
? Większość architektur będzie przechowywać zwracaną wartość funkcji w rejestrze, aint
znak będzie pasował do rejestru tak samo dobrze, jakshort
lubchar
. A używaniechar
dla typów liczbowych jest zawsze złym pomysłem, zwłaszcza gdy trzeba zagwarantować, że podpisane wartości są obsługiwane poprawnie.char
byłoby złym pomysłem, ponieważ sprawdzanie kodu pod kątem wartości zwracanej, jeśli jest mniejsza od zera, zakończy się niepowodzeniem na platformach, na którychchar
jest bez znaku.Odpowiedzi:
Po pierwsze, specyfikacja jest taka, że zwróci wartość mniejszą niż, równą lub większą niż
0
, niekoniecznie-1
lub1
. Po drugie, zwracane wartości to rvalues podlegające integralnej promocji, więc nie ma sensu zwracać niczego mniejszego.W C ++ (podobnie jak w C) każde wyrażenie jest albo wartością r, albo lwartością. Historycznie, terminy te odnoszą się do faktu, że lwartości pojawiają się po lewej stronie przydziału, podczas gdy jako rwartości mogą pojawiać się tylko po prawej stronie. Obecnie prostym przybliżeniem dla typów nieklasowych jest to, że l-wartość ma adres w pamięci, a r-wartość nie. Dlatego nie możesz wziąć adresu wartości r, a kwalifikatory cv (których warunek „dostęp”) nie mają zastosowania. W terminologii C ++ rwartość, która nie ma typu klasy, jest czystą wartością, a nie obiektem. Wartość zwracana funkcji jest wartością r, chyba że ma typ referencyjny. (Typy nieklasowe, które mieszczą się w rejestrze, prawie zawsze będą zwracane na przykład w rejestrze, a nie w pamięci).
W przypadku typów klas problemy są nieco bardziej złożone, ze względu na fakt, że można wywoływać funkcje składowe na wartości r. Oznacza to, że wartości r muszą w rzeczywistości mieć adresy dla
this
wskaźnika i mogą być kwalifikowane jako cv, ponieważ kwalifikacja cv odgrywa rolę w rozwiązywaniu przeciążeń. Wreszcie, C ++ 11 wprowadza kilka nowych rozróżnień, aby wspierać odwołania do rvalue; te również mają zastosowanie głównie do typów klas.Promocja integralna odnosi się do faktu, że gdy typy całkowite mniejsze niż an
int
są używane jako rwartości w wyrażeniu, w większości kontekstów będą promowaneint
. Więc nawet jeśli mam zadeklarowaną zmiennąshort a, b;
, w wyrażeniua + b
obiea
ib
są promowaneint
przed dodaniem. Podobnie, jeśli napiszęa < 0
, porównanie odbywa się na wartościa
, przekonwertowanej naint
. W praktyce jest bardzo niewiele przypadków, w których ma to znaczenie, przynajmniej na maszynach 2 uzupełniających, w których zawija się arytmetykę liczb całkowitych (tj. Wszystkie oprócz bardzo nielicznych egzotyków, dziś - myślę, że jedynymi pozostałymi wyjątkami są komputery mainframe Unisys). Mimo to, nawet na bardziej popularnych komputerach:powinny dawać różne wyniki: pierwszy jest odpowiednikiem
sizeof( short )
, drugisizeof( int )
(ze względu na integralną promocję).Te dwie kwestie są formalnie ortogonalne; rvalues i lvalues nie mają nic wspólnego z integralną promocją. Z wyjątkiem ... integralna promocja dotyczy tylko wartości r, a większość (ale nie wszystkie) przypadków, w których użyjesz wartości r, spowoduje integralną promocję. Z tego powodu naprawdę nie ma powodu, aby zwracać wartość liczbową w czymś mniejszym niż
int
. Jest nawet bardzo dobry powód, aby nie zwracać go jako typu znakowego. Przeciążone operatory, takie jak<<
, często zachowują się inaczej w przypadku typów znaków, więc chcesz zwracać tylko znaki jako typy znaków. (Możesz porównać różnicę:Różnica polega na tym, że w drugim przypadku dodanie spowodowało wystąpienie promocji integralnej, co skutkuje
<<
wybraniem innego przeciążenia .źródło
return values are rvalues, subject to integral promotion
w swojej odpowiedzi.signed char
? Czy zachowywałby się tak samo jak podpisanychar
, czy byłby innego typu?Jest celowe, że nie zwraca -1, 0 lub 1.
Pozwala (uwaga: nie dotyczy to strun, ale dotyczy to również strun)
co jest dużo mniej uciążliwe niż:
czyli co musiałbyś zrobić [lub coś w tych liniach], jeśli musisz zwrócić -1, 0 lub 1.
Działa to również w przypadku bardziej złożonych typów:
W przypadku stringów możemy to zrobić:
źródło
compare
funkcja ma problemy z przepełnieniem, które (na szczęście) nie mają jednakowego zastosowania, jeśli zajmujechar*
ichar
jest mniejsze niżint
. Na przykład, jeśli*a
jestMAX_INT
i*b
jest,-1
to*a - *b
jest UB, ale jeśli implementacja zdecyduje się zdefiniować swoje zachowanie, wynik prawie na pewno jest ujemny.length()
zwraca wartość asize_t
, która może być większa niżint
…int jest zwykle (co oznacza na większości współczesnych urządzeń) liczbą całkowitą o takim samym rozmiarze jak magistrala systemowa i / lub rejestry procesora, czyli tak zwane słowo maszynowe. Dlatego int jest zwykle przekazywany szybciej niż mniejsze typy, ponieważ nie wymaga wyrównywania, maskowania i innych operacji.
Mniejsze typy istnieją głównie po to, aby umożliwić optymalizację wykorzystania pamięci RAM dla tablic i struktur. W większości przypadków wymieniają kilka cykli procesora (w formie operacji dopasowywania) na lepsze wykorzystanie pamięci RAM.
O ile nie musisz wymuszać, aby zwracana wartość była liczbą ze znakiem lub bez znaku o wielkości centa (znak, krótki…), lepiej jest używać int, dlatego robi to biblioteka standardowa.
źródło
To jest C-izm.
Gdy C wymagało
compare
funkcji typu -type, zawsze zwracały plikint
. C ++ po prostu poszedł naprzód (niestety).Jednak zwrot
int
jest prawdopodobnie najszybszym sposobem, ponieważ zazwyczaj jest to rozmiar rejestrów używanego systemu. (Celowo niejasne.)źródło
short
ichar
może nakładać kary za wydajność, np.255+7
Ma inną wartość dlachar
ai,int
więc prawidłowa implementacja nie musi koniecznie po prostu przechowywać a,char
gdzieint
może przejść, nie dbając o przekazanie jego semantyki. Kompilatory niekoniecznie optymalizują wynikającą z tego nieefektywność.Metoda w rzeczywistości nie zwraca liczby całkowitej w zestawie
{ -1, 0, 1 }
; w rzeczywistości może to być dowolna wartość całkowita.Czemu? Główny powód, jaki przychodzi mi do głowy, jest taki, że
int
ma to być wartość „naturalnej wielkości” architektury; operacje na wartościach tego rozmiaru są zwykle co najmniej tak samo szybkie (aw wielu przypadkach szybsze) niż operacje na mniejszych lub większych wartościach. Jest to więc przypadek, w którym implementacja jest wystarczająco wolna, aby używać tego, co jest najszybsze.źródło
Byłby to dobry pomysł. Lepszym sposobem byłoby zwrócenie wartości bool (jeśli tylko chcesz porównać, jeśli równa się) lub wyliczenia (aby uzyskać więcej informacji):
źródło
Załóżmy, że niektórzy ludzie zmieniają kod z C na C ++. Postanowili zamienić
strcmp
nastring::compare
.Ponieważ
strcmp
wracaint
, łatwiej jeststring::compare
zwrócićint
jako prezent.źródło
Prawdopodobnie, aby działało bardziej jak,
strcmp
który również ma ten zestaw wartości zwracanych . Jeśli chciałbyś przenieść kod, prawdopodobnie byłoby bardziej intuicyjne, gdyby zamienniki były tak blisko, jak to tylko możliwe.Ponadto, wartość zwracana jest nie tylko
-1
,0
czy1
jednak<0
,0
czy>0
.Ponadto, jak wspomniano, skoro zwrot podlega integralnej promocji , nie ma sensu go zmniejszać.
źródło
ponieważ logiczna wartość zwracana może być tylko dwiema możliwymi wartościami (prawda, fałsz), a funkcja porównująca może zwracać trzy możliwe wartości (mniejsze niż, równe, większe niż).
Aktualizacja
Chociaż z pewnością możliwe jest zwrócenie podpisanego skrótu, jeśli naprawdę chcesz zaimplementować własną funkcję porównującą, możesz zwrócić wartość nibble lub struct z dwoma parametrami logicznymi.
źródło
short
ichar
jako alternatywę dlaint
.