c#
c++
c
unary-operator
vrish88
źródło
źródło
Odpowiedzi:
Jest tam, aby być przeciążonym, jeśli poczujesz potrzebę; dla wszystkich predefiniowanych typów jest to w zasadzie zakaz.
Praktyczne zastosowania jednoargumentowego operatora arytmetycznego no-op są dość ograniczone i zwykle odnoszą się do konsekwencji użycia wartości w wyrażeniu arytmetycznym, a nie samego operatora. Na przykład można jej użyć do wymuszenia poszerzenia z mniejszych typów całkowitych do
int
lub zapewnienia, że wynik wyrażenia jest traktowany jako wartość r, a zatem nie jest zgodny zconst
parametrem nie będącym referencją. Uważam jednak, że te zastosowania lepiej nadają się do kodowania golfa niż do czytelności. :-)źródło
int
i skutkujące rvalue są efektami wyrażenia -ness, a nie samego operatora +.W rzeczywistości jednoargumentowy plus robi coś - nawet w C. Wykonuje zwykłe konwersje arytmetyczne na operandzie i zwraca nową wartość, która może być liczbą całkowitą o większej szerokości. Jeśli oryginalna wartość była liczbą całkowitą bez znaku o mniejszej szerokości niż
int
, zostanie również zmieniona nasigned
wartość.Zwykle nie jest to aż tak ważne, ale może mieć wpływ, więc nie jest dobrym pomysłem używanie jednoargumentowego plusa jako pewnego rodzaju „komentarza” oznaczającego, że liczba całkowita jest dodatnia. Rozważmy następujący program w C ++:
void foo(unsigned short x) { std::cout << "x is an unsigned short" << std::endl; } void foo(int x) { std::cout << "x is an int" << std::endl; } int main() { unsigned short x = 5; foo(+x); }
Spowoduje to wyświetlenie „x to int”.
Więc w tym przykładzie jednoargumentowy plus utworzył nową wartość z innym typem i podpisem.
źródło
an integer of greater width
?Z drugiej edycji K&R:
źródło
Widziałem, że jest używany dla jasności, aby podkreślić wartość dodatnią w odróżnieniu od wartości ujemnej:
shift(+1); shift(-1);
Ale to dość słabe zastosowanie. Odpowiedź jest zdecydowanie przeładowana.
źródło
vec3(+1,-1,-1)
Jedną z rzeczy, które
+
robi wbudowana jednostka jednoargumentowa , jest zamiana lvalue na rvalue. Na przykład możesz to zrobićint x; &x;
ale nie możesz tego zrobić
:)
PS „Przeciążanie” zdecydowanie nie jest właściwą odpowiedzią. Jednoargumentowe
+
zostało odziedziczone z C i nie ma przeciążenia operatora na poziomie użytkownika w C.źródło
Najważniejsze, co osiąga + unary, to promocja typu na int dla typów danych mniejszych niż int. Może to być bardzo przydatne, jeśli próbujesz wydrukować dane typu char
std::cout
jako dane liczbowe.char x = 5; std::cout << +x << "\n";
bardzo różni się od
char x=5; std::cout << x << "\n";
Jest również dostępny do przeciążania, ale w praktyce przeciążenie powinno wynosić prawie NOP.
źródło
Jeśli kiedykolwiek będziesz musiał wydrukować wartość liczbową surowych bajtów (np. Małe liczby przechowywane jako znaki) w celu debugowania lub z jakiegokolwiek powodu, jednoargumentowe + może uprościć kod drukowania. Rozważać
char c = 42; cout << c << endl; // prints "*\n", not what you want in this case cout << (int)c << endl; // prints "42\n", ok cout << +c << endl; // prints "42\n", much easier to type
To tylko szybki przykład. Jestem pewien, że są inne przypadki, kiedy jednoargumentowe + może pomóc traktować twoje bajty bardziej jak liczby, a nie jak tekst.
źródło
Ciekawostka historyczna. Komitet normalizacyjny C99 również uważał, że istniejące zastosowania unarnikowego plusa są dość rzadkie, o czym świadczy rozważenie ponownego użycia go w celu osiągnięcia innej cechy w języku: zahamowania oceny czasu tłumaczenia stałych wyrażeń zmiennoprzecinkowych. Patrz następujący cytat z uzasadnienia C, sekcja F.7.4:
Ostatecznie semantyka została odwrócona, z oceną w czasie wykonywania wymuszoną w większości kontekstów (przynajmniej do reguły „jak gdyby”) i możliwością wymuszenia oceny czasu tłumaczenia za pomocą statycznych inicjatorów. Zauważ, że główna różnica polega na występowaniu wyjątków zmiennoprzecinkowych i innych ustawieniach zaokrąglania zmiennoprzecinkowego lub precyzji, jeśli są obecne.
źródło
Niewiele. Ogólnym argumentem przemawiającym za zezwoleniem na przeciążenie
operator+()
jest to, że zdecydowanie istnieją rzeczywiste zastosowania przeciążaniaoperator-()
i byłoby bardzo dziwne (lub asymetryczne), gdybyś pozwolił na przeciążenie,operator-()
ale nieoperator+()
.Wydaje mi się, że najpierw przeczytałem ten argument od Stroustropa, ale nie mam przy sobie moich książek, aby to zweryfikować. Mogę się mylić.
źródło
Unary plus był obecny w C, gdzie nie robił absolutnie nic (podobnie jak
auto
słowo kluczowe). Aby go nie mieć, Stroustrup musiałby wprowadzić nieuzasadnioną niezgodność z C.Kiedyś był w C ++, naturalne było zezwolenie na funkcję przeciążającą, taką jak jednoargumentowy minus, i Stroustrup mógł ją wprowadzić z tego powodu, gdyby jeszcze jej tam nie było.
Więc to nic nie znaczy. Może być używany jako rodzaj dekoracji, aby rzeczy wyglądały bardziej symetrycznie, używając na przykład +1,5 jako przeciwieństwa do -1,5. W C ++ może być przeciążony, ale może być mylący, jeśli
operator+()
coś zrobi. Pamiętaj o standardowej zasadzie: przeciążając operatory arytmetyczne, rób rzeczy takie jakint
s.Jeśli szukasz powodu, dla którego tam jest, znajdź coś o wczesnej historii C. Podejrzewam, że nie było dobrego powodu, ponieważ C nie został tak naprawdę zaprojektowany. Rozważ bezużyteczne
auto
słowo kluczowe (prawdopodobnie w przeciwieństwie do tegostatic
, które jest teraz odtwarzane w C ++ 0x) ientry
słowo kluczowe, które nigdy nic nie zrobiło (a później zostało pominięte w C90). Jest słynny e-mail, w którym Ritchie lub Kernighan mówią, że kiedy zdali sobie sprawę, że pierwszeństwo operatorów ma problemy, istniały już trzy instalacje z tysiącami linii kodu, których nie chcieli złamać.źródło
entry
: ( stackoverflow.com/q/254395/153285 ). W dzisiejszych czasach, jeśli chcesz mieć wiele punktów wejścia, po prostu użyj wywołań końcowych i optymalizacji sterowanej profilem.extern volatile int foo;
, kompilator, który otrzyma instrukcję,+foo;
byłby zobowiązany do wykonania odczytu wskazanego adresu na dowolnej platformie, na której możliwe byłoby istnienie jakichkolwiek środków, aby stwierdzić, że odczyt miał miejsce. Nie jestem pewien, czy byłoby to wymagane, gdyby instrukcja zawierała po prostu "foo", chociaż wielu kompilatorów zrobi to grzecznościowo.Nie mogę cytować żadnego źródła tego, ale zrozumiałem, że dotyczy to jawnej promocji typu, co oznacza bezstratną konwersję typów. To stawia go na szczycie hierarchii konwersji,
new_type operator+(old_type)
new_type(old_type)
operator(new_type)(old_type)
new_type operator=(old_type)
Oczywiście wynika to z mojej interpretacji notatki w jednym z (naprawdę starych) podręczników c / c ++ firmy Microsoft, które przeczytałem około 15 lat temu, więc traktuj to z przymrużeniem oka.
źródło
#include <stdio.h> int main() { unsigned short x = 5; printf ("%d\n",sizeof(+x)); printf ("%d\n",sizeof(x)); return 0; }
Jak pokazano w powyższym przykładzie, jednoargumentowy + naprawdę zmienia typ, odpowiednio rozmiar 4 i 2. Dziwne, że wyrażenie + x jest rzeczywiście obliczane w rozmiarze sizeof, pomyślałem, że nie powinno. Być może wynika to z faktu, że sizeof ma taki sam priorytet jak jednoargumentowe +.
źródło
Przypuszczam, że możesz go użyć, aby zawsze uzyskać dodatnią liczbę. Po prostu przeładuj jednoargumentowy operator +, aby był abs. Naprawdę nie warto mylić innych programistów, chyba że naprawdę chcesz zaciemnić swój kod. Wtedy będzie dobrze działać.
źródło
~
? Nie jestem pewien, jaka jest twoja definicja „przeciwieństwa”, ale podejrzewam, że jest ona obciążona doświadczeniem tego, co obecnie robią jednoargumentowy plus i jednoargumentowy minus.EDYCJA Przepisałem całkowicie, bo waaaayyy w mojej oryginalnej odpowiedzi.
Powinno to pozwolić ci obsłużyć jawną deklarację twojego typu jako wartość dodatnią (myślę, że w większości operacji niematematycznych). Wydaje się, że negacja byłaby bardziej przydatna, ale wydaje mi się, że oto przykład, gdzie może mieć znaczenie:
public struct Acceleration { private readonly decimal rate; private readonly Vector vector; public Acceleration(decimal rate, Vector vector) { this.vector = vector; this.rate = rate; } public static Acceleration operator +(Acceleration other) { if (other.Vector.Z >= 0) { return other; } return new Acceleration(other.Rate, new Vector(other.vector.X, other.Vector.Y, -other.vector.Z)); } public static Acceleration operator -(Acceleration other) { if (other.Vector.Z <= 0) { return other; } return new Acceleration(other.Rate, new Vector(other.vector.X, other.Vector.Y, -other.vector.Z)); } public decimal Rate { get { return rate; } } public Vector Vector { get { return vector; } } }
źródło
+
nie polega na nadaniu wartości dodatniej, ale na pozostawieniu jej znaku bez zmian.po prostu to służyło do przekonania, które liczby są dodatnie
na przykład;
int a=10; System.out.println(+x);// prints 10(that means,that number 10 multiply by +1,{10*+1}) //if we use unary minus int a=10; System.out.println(-x);//prints -10(that means,that number 10 multiply by +1,{10*-1})
źródło