Czy wszystkie operatory C ++ zwracają coś?


83

Wszystkie operatory C ++, z którymi pracowałem, zwracają coś, na przykład +operator zwraca wynik dodawania.

Czy wszystkie operatory C ++ zwracają coś, czy też istnieją operatory C ++, które nic nie zwracają?


7
Zależy to od tego, jak wąsko zdefiniujesz termin „operator”.
molbdnilo

12
Nie jest to wymuszone przez standard - można na przykład zaimplementować +=powrót void, ale nie jest to zalecane. Również operatorzy wywołań funkcji mogą powrócić voidi jest to ważne
Mircea Ispas

Hmm. Mam przeczucie, że operator rozpoznawania zakresu ::nic nie zwraca, ale musiałbym sprawdzić standard, aby się upewnić.
Yksisarvinen

2
Czy kontekst pytania dotyczy tylko typów podanych w języku C ++, czy też obejmuje typy zdefiniowane przez użytkownika?
Eljay

@Eljay Tylko typy dostarczone przez C ++.
user8240761

Odpowiedzi:


112

Nie, nie wszyscy operatorzy coś zwracają.

Chociaż prawdopodobnie nie są one dokładnie tym , o czym myślisz, zwróć uwagę, że „słowa kluczowe” deletei delete[]C ++ są w rzeczywistości operatorami ; i są zdefiniowane jako mające voidtyp zwracany - co oznacza, że wartościowane do niczego (co nie jest „czymś”).

Od cppreference :

void operator delete  ( void* ptr ) noexcept;
void operator delete[]( void* ptr ) noexcept;

13
Podoba mi się twoja odpowiedź, to sprawiło, że zacząłem myśleć inaczej. delete, delete[], throw, (void)x;Obsada, z lewej strony ,operatora, po prawej stronie ,operatora, który daje void, A ?:trójskładnikowy, który używa throwjednego z ramion, dfri jest operator void()(co będzie określone przez użytkownika),眠りネロクjest void operator()()(zdefiniowana co byłoby użytkownika).
Eljay

10
Mylące jest również to, że deleteoperator niszczy obiekt, a następnie wywołuje operator delete. Ergo, deleteoperator i operator deletesą oddzielnymi rzeczami :( stackoverflow.com/a/8918942/845092
Mooing Duck

7
Nie jestem pewien, dlaczego cytujesz funkcje delete, mówiąc o operatorze delete. Ale cokolwiek.
Deduplicator

4
@MooingDuck Wyrażenie delete niszczy obiekt, a następnie wywołuje operator delete.
NathanOliver

Czy usuwanie liczy się jako operator przez, myślałem, że obiekt jest czymś, co działa na przekazywanym obiekcie? Usuwanie nie potrzebuje żadnego obiektu mają być przekazywane lub utworzone dla niego do pracy ..... Tak jak printf .....
Yunfei Chen

82

Operatorzy niestandardowych typów mogą być przeciążeni, aby robić najdziwniejsze rzeczy.

na przykład operator + zwraca wynik dodawania.

Niekoniecznie:

#include <iostream>
struct foo {
    int value = 0;
    void operator+(int x) {
        value += x;
    }
};

int main () {
    foo f;
    f + 3;
}

Tutaj operator+dodaje lewą stronę do elementu valueczłonkowskiego, a jego zwracany typ jest nieważny. To jest zmyślony przykład, ale generalnie nie zwracanie czegoś od operatora niestandardowego nie jest niczym niezwykłym.

Jedynym operatorem, który może być przeciążony i który wymaga zwrócenia czegoś, o czym jestem świadomy, jest operator->. Musi zwracać surowy wskaźnik lub obiekt, który ma rozszerzenie operator->.


Co zabawne, w rzeczywistości nie ma ograniczenia na zwracanie wartości przez przeciążone operatory. Tak więc operatorzy mogą zwracać, co chcesz. en.cppreference.com/w/cpp/language/operators
bracco23

5
@ braccor23 operator->jest trochę specjalne i musi zwrócić wskaźnik lub obiekt, który ma operator->, nie jestem pewien, czy są inne wyjątki
największych_prime_is_463035818

1
Tak, to jedyne ograniczenie. Nawet nie bool dla operatorów porównania. To wygląda naprawdę dziwnie.
bracco23

9
@ idclev463035818: Być może bardziej użytecznym przykładem mogą być Szablony wyrażeń. Na przykład, możesz utworzyć bibliotekę macierzy, w której operator*(Matrix const& left, Matrix const& right)nie zwraca, Matrixale zamiast tego MatrixMul, tak że jeśli jest następnie wprowadzana do operator+(Matrix const& left, MatrixMul const& right)operacji, może być połączonym mnożeniem i dodawaniem, co jest bardziej wydajne niż najpierw mnożenie, a następnie dodawanie.
Matthieu M.,

1
@DarrelHoffman Gdy operacje we / wy <<i >>są przeciążone, oczekuje się, że zwrócą strumień, aby można było je kaskadować:stream << foo << bar;
Barmar

34

Operatorzy nic nie zwracają. To tylko elementy leksykalne, których używamy do tworzenia wyrażeń w języku. Teraz wyrażenia mają typy i mogą być obliczane na wartości i zakładam, że to właśnie masz na myśli, mówiąc o operatorach „zwracających rzeczy”.

I cóż, tak. Istnieją wyrażenia C ++ z typem void(w związku z czym nie dają żadnej wartości). Niektóre są oczywiste, inne mniej. Dobrym przykładem może być

throw std::runtime_error()

throwjest wyrażeniem w gramatyce C ++. Możesz go używać w innych wyrażeniach, na przykład w wyrażeniu warunkowym

return goodStatus() ? getValue() : throw std::runtime_error();

A typ wyrażenia rzut to void. Oczywiście, ponieważ powoduje to po prostu szybkie przejście w inne miejsce, wyrażenie nie ma wartości.


21

Żaden z wbudowanych operatorów C ++ niczego nie zwraca . Przeciążone operatory C ++ zwracają coś, o ile notacja operatora jest cukrem składniowym dla wywołania funkcji.

Raczej wszyscy operatorzy oceniają coś. To coś ma dobrze zdefiniowaną wartość, a także typ . Nawet operator wywołania funkcji void operator()(/*params*/)jest voidtypem.

Na przykład +'a'jest inttypem o wartości 'a'zakodowanej na Twojej platformie.

Jeśli Twoje pytanie brzmi „Czy operatory C ++ mogą mieć voidzwracany typ?” wtedy odpowiedź brzmi z całą pewnością tak.


14
@ idclev463035818: Jest to zwrot terminu , z którym mam problem. Jedyną rzeczą w C ++, która coś zwraca, jest funkcja. Ekspresja oceniać coś.
Batszeba

7
operatory typów klas to metody, które coś zwracają
największych_prime_is_463035818

4
To jest ważna kwestia. Niedbała terminologia prowadzi do nieporozumień. +1.
Pete Becker

3
@supercat - Twój komentarz obraża grupę ciężko pracujących ludzi, w tym mnie. Ci z nas, którzy napisali standard, nigdy nie spodziewali się, że autorzy kompilatorów będą wypełniać szczegóły przez odpytywanie innych kompilatorów, obecnych lub przeszłych. Celem standardu było i jest jasne zdefiniowanie składni i semantyki języka programowania C ++. Tak, wynik nie jest doskonały; istnieje wiele problemów rozwiązanych w najnowszym standardzie, które nie zostały rozwiązane we wcześniejszych wersjach. Wynika to z doświadczenia, rozpoznawania komplikacji, których po prostu wtedy nie widziano.
Pete Becker

3
@ Peter-ReinstateMonica - oto silniejsza wersja. Wyrażenie I++nie zwraca wartości. Jeśli typ ijest typem zdefiniowanym przez użytkownika, to wyrażenie jest implementowane jako operator++funkcja, która zwraca wartość. Nazywasz to „cukrem syntaktycznym”; Nazywam to rozróżnieniem, które ma ważne konsekwencje.
Pete Becker

12

W rzeczywistości można zdefiniować operator wywołania funkcji, aby nic nie zwracał. Na przykład:

struct Task {
   void operator()() const;
};

17
Możesz zdefiniować prawie każdego operatora, aby nic nie
zwracał

7
@Yksisarvinen, ale przynajmniej ten jest potencjalnie przydatny.
Mark Ransom

11

operator void (): funkcja konwersji zdefiniowana przez użytkownika na void

Możesz określić osobliwy operator void()funkcji konwersji, gdzie kompilator będzie nawet cię ostrzec, że Tdo voidfunkcji konwersji nigdy nie zostaną wykorzystane :

#include <iostream>

struct Foo {
    operator void() { std::cout << "Foo::operator void()!"; }
    // warning: conversion function converting 'Foo' to 
    //          'void' will never be used
};
    
int main() {
    Foo f;
    (void)f;            // nothing
    f.operator void();  // Foo::operator void()!
}

zgodnie z [class.conv.fct] / 1

[...] Funkcja konwersji A nigdy stosowane do konwersji (ewentualnie CV zastrzeżeniami) przedmiotu do tego typu obiektu (ewentualnie CV zastrzeżeniami) (albo w odniesieniu do niej) do (ewentualnie cv wykwalifikowany) klasy bazowej tego typu (lub odniesienie do niego) lub do (prawdopodobnie kwalifikowane jako cv) void. 117

( 117 ) Te konwersje są uważane za konwersje standardowe do celów rozwiązania problemu z przeciążeniem ([over.best.ics], [over.ics.ref]), a zatem inicjalizacji ([dcl.init]) i rzutów jawnych. Konwersja do voidnie wywołuje żadnej funkcji konwersji ([wyrażenie.static.cast]). Chociaż nigdy nie są bezpośrednio wywoływane w celu wykonania konwersji, takie funkcje konwersji mogą być zadeklarowane i potencjalnie mogą być osiągnięte przez wywołanie wirtualnej funkcji konwersji w klasie bazowej.

Chociaż jednak, jak pokazano powyżej, nadal można go wywołać przy użyciu jawnej .operator void()składni.


4

Operatory zdefiniowane (wbudowane) przez język to tokeny używane do wykonywania różnego rodzaju obliczeń:

  • arytmetyczne (+, -, *, /)
  • zwiększanie / zmniejszanie (++, -)
  • przypisanie (=, + =, - =, * =, / =,% =, >> =, << =, & =, ^ =, | =)
  • logika (!, &&, ||)
  • relacyjny (==,! =,>, <,> =, <=)
  • warunkowy ?
  • przecinek

i tak dalej. Lista może być bardzo obszerna.

W odniesień językowych, takich jak ta, lub ten , te niekoniecznie są oznaczone jako powrocie coś, po prostu wykonywania arytmetyczne lub logiczne działanie , przez porównanie, co oznacza zmienną mogą być modyfikowane, etc.

Ponieważ ta operacja daje pewną wartość, może być zinterpretowana jako „zwrócona” przez operator, ale różni się od wartości zwracanej przez funkcję.

Z drugiej strony, przeciążone operatory można zdefiniować za pomocą wartości zwracanej pewnego typu, nawet jeśli może to być wartość void, więc nie, nie wszystkie operatory zwracają jakąś wartość w C ++.


3

Zakładam, że mówisz o funkcjach operatora, a nie o operatorach jako jednostce składniowej języka.

Jeśli przeciążasz operatory dowolnego typu, możesz w rzeczywistości zwrócić, co chcesz.

Ma to również duży sens, ponieważ operacje takie jak * lub () mogą czasami bardzo intuicyjnie nie zwracać typu danych wejściowych. Wyobraź sobie, że mnożymy typ liczb zespolonych przez typ liczb rzeczywistych. Lub operator, który zwraca element z kolekcji.

Możesz również przeciążać operatory ++ i -, aby nic nie zwracały, usuwając w ten sposób wyjątkowo podatne na błędy mieszanie efektu ubocznego i wartości wyrażenia, które ma wersja standardowa.


2

Nie. Rozważ te dwa przykłady tutaj:

int multiply (int a, int b) {
   return a*b;
}

void multiply_void(int a, int b) {
   cout << a*b;
//or cout << multiply(a,b);
}

Pierwsza funkcja zwróci wartość całkowitą, której może użyć inna funkcja. Wartość jest zwracana i zapisywana w pamięci do wykorzystania w razie potrzeby. Jeśli nie, nie jest to widoczne dla człowieka i po prostu szczęśliwie pozostaje w pamięci.

Druga funkcja wyprowadzi dane do domyślnego urządzenia wyjściowego (zwykle konsoli). Wartość zwracana przez operator mnożenia jest przekazywana do urządzenia wyjściowego. Funkcja multiply_void nie zwraca rzeczywistej wartości.


0

Wszyscy operatorzy coś zwracają. Nazywa się je operatorami, ponieważ coś operują, dlatego coś zwrócą. Operatorzy, którzy czegoś nie zwracają, nie mogą nazywać się operatorami. Albo zwrócą jakąś wartość, albo zwrócą True lub False, w zależności od sytuacji.


0

Operatorzy sami nie zawsze nic zwracają. Wywołania funkcji zwracają wartości. Operatory mogą dawać wartości. Operatory mogą czasami wywoływać funkcje. Przykłady zawierają:

• Operator wywołania funkcji.

• Przeciążony operator, który zostaje przekształcony w wywołanie funkcji.

• operator new, który jest wywoływany jako część nowego wyrażenia , jest wywołaniem funkcji.

Moim jedynym celem przy wspominaniu wywołań funkcji jest wyjaśnienie wyniku w stosunku do zwrotu. Opierając się na analizie wszystkich 126 wystąpień wyrażenia „return” i wyprowadzonych z niego słów w [wyraż] , sekcja wydaje się uważnie używać słowa return w odniesieniu do:

• wynik wywołania funkcji

• aspekty przepływu kontroli związane z programami

OK, wystarczy pedanterii w kwestii wyniku vs. zwrot.


0

Operatory C ++ zwracają coś lub nie, zależy od tego, jak ich użyłeś. Wbudowane operatory C ++ zwracają pewną wartość, dopóki nie zostaną wymuszone, aby zwrócić void.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.