Operátorok C és C++ nyelven

Az oldal jelenlegi verzióját még nem ellenőrizték tapasztalt közreműködők, és jelentősen eltérhet a 2022. szeptember 13-án felülvizsgált verziótól ; az ellenőrzéshez 1 szerkesztés szükséges .

A C++ programozási nyelv támogatja elődjének, a C-nek az összes operátorát, és új operátorokkal és szolgáltatásokkal bővült.

Az első operandus kiértékelése után nem túlterhelt " && " operátorokhoz , " || ” és „ , ” (a „vessző” operátor, angol  vessző ) a fordító beszúr egy szekvenciapontot ( eng.  sequence point ), amely garantálja, hogy minden mellékhatás (például a „postfix ++” operátor) végrehajtásra kerül a második operandus kiértékelése előtt.

A C-szerű szintaxisú nyelvek (mint például a Java , C# , PHP és mások) gyakran kölcsönöznek C/C++ operátorokat, megőrizve nemcsak viselkedésüket, hanem elsőbbségüket és asszociativitásukat is .

Táblázatok

A táblázatok a következő jelöléseket használják:

struct T { // vagy osztályoperátor float ( ) const ; }; T :: operátor float () const { /* implementáció */ };
  • "Osztályon kívüli definíció": operátor definiálása függvényként; példa:
#include <iostream> struct T { // vagy osztály /* ... */ }; std :: ostream & operátor << ( std :: ostream & a , T const & b ) { /* implementáció */ }
  • "N/A" : Nem elérhető .

Aritmetikai operátorok

Művelet (kifejezés) Operátor Kifejezés szintaxisa Túlterhelhető C -ben végrehajtva Példa
T típusú tag Definíció az osztályon kívül
Feladat = a = b Igen Igen R& T::operator =(S b); n/a
Kiegészítés + a + b Igen Igen R T::operator +(S b); R operator +(T a, S b);
Kivonás - a - b Igen Igen R T::operator -(S b); R operator -(T a, S b);
egységes plusz + +a Igen Igen R T::operator +(); R operator +(T a);
egységes mínusz - -a Igen Igen R T::operator -(); R operator -(T a);
Szorzás * a * b Igen Igen R T::operator *(S b); R operator *(T a, S b);
Osztály / a / b Igen Igen R T::operator /(S b); R operator /(T a, S b);
Műveleti modulus ( az egész számok osztásából származó maradék ) [1. megjegyzés] % a % b Igen Igen R T::operator %(S b); R operator %(T a, S b);
Növekedés előtag ++ ++a Igen Igen R& T::operator ++(); R& operator ++(T a);
utótag (utótag) ++ a++ Igen Igen R T::operator ++(int); R operator ++(T a, int);
[jegyzet 2]
Csökkenés előtag -- --a Igen Igen R& T::operator --(); R& operator --(T a);
utótag (utótag) -- a-- Igen Igen R T::operator --(int); R operator --(T a, int);
[jegyzet 2]

Összehasonlító operátorok

Művelet (kifejezés) Operátor Kifejezés szintaxisa Túlterhelhető C -ben végrehajtva Példa
T típusú tag Definíció az osztályon kívül
Egyenlőség == a == b Igen Igen R T::operator ==(S b); R operator ==(T a, S b);
Egyenlőtlenség != a != b Igen Igen R T::operator !=(S b); R operator !=(T a, S b);
Több > a > b Igen Igen R T::operator >(S b); R operator >(T a, S b);
Kevésbé < a < b Igen Igen R T::operator <(S b); R operator <(T a, S b);
Több vagy egyenlő >= a >= b Igen Igen R T::operator >=(S b); R operator >=(T a, S b);
Kisebb vagy egyenlő <= a <= b Igen Igen R T::operator <=(S b); R operator <=(T a, S b);

Logikai operátorok

Művelet (kifejezés) Operátor Kifejezés szintaxisa Túlterhelhető C -ben végrehajtva Példa
T típusú tag Definíció az osztályon kívül
Logikai tagadás, NEM ! !a Igen Igen R T::operator !(); R operator !(T a);
Logikai szorzás, ÉS && a && b Igen Igen R T::operator &&(S b); R operator &&(T a, S b);
Logikai összeadás, VAGY || a || b Igen Igen R T::operator ||(S b); R operator ||(T a, S b);

Bitenkénti operátorok

Művelet (kifejezés) Operátor Kifejezés szintaxisa Túlterhelhető C -ben végrehajtva Példa
T típusú tag Definíció az osztályon kívül
bitenkénti inverzió ~ ~a Igen Igen R T::operator ~(); R operator ~(T a);
Bitenként ÉS & a & b Igen Igen R T::operator &(S b); R operator &(T a, S b);
Bitenként VAGY (vagy) | a | b Igen Igen R T::operator |(S b); R operator |(T a, S b);
Bitenkénti XOR (xor) ^ a ^ b Igen Igen R T::operator ^(S b); R operator ^(T a, S b);
Bitenkénti bal eltolás [3. megjegyzés] << a << b Igen Igen R T::operator <<(S b); R operator <<(T a, S b);
Biteltolás jobbra [3. megjegyzés] [4. megjegyzés] >> a >> b Igen Igen R T::operator >>(S b); R operator >>(T a, S b);

Összetett hozzárendelés

Művelet (kifejezés) Operátor Kifejezés szintaxisa Jelentése Túlterhelhető C -ben végrehajtva Példa
T típusú tag Definíció az osztályon kívül
Kiegészítés megbízással kombinálva += a += b a = a + b Igen Igen R T::operator +=(S b); R operator +=(T a, S b);
Kivonás hozzárendeléssel kombinálva -= a -= b a = a - b Igen Igen R T::operator -=(S b); R operator -=(T a, S b);
Szorzás hozzárendeléssel kombinálva *= a *= b a = a * b Igen Igen R T::operator *=(S b); R operator *=(T a, S b);
Megosztással egybekötve /= a /= b a = a / b Igen Igen R T::operator /=(S b); R operator /=(T a, S b);
A felosztás fennmaradó része a megbízással kombinálva [1. megjegyzés] %= a %= b a = a % b Igen Igen R T::operator %=(S b); R operator %=(T a, S b);
Bitenkénti „ÉS” hozzárendeléssel kombinálva &= a &= b a = a & b Igen Igen R T::operator &=(S b); R operator &=(T a, S b);
Bitenkénti "OR" (vagy) hozzárendeléssel kombinálva |= a |= b a = a | b Igen Igen R T::operator |=(S b); R operator |=(T a, S b);
Bitenkénti kizárólagos VAGY (xor) hozzárendeléssel kombinálva ^= a ^= b a = a ^ b Igen Igen R T::operator ^=(S b); R operator ^=(T a, S b);
Bitenkénti bal eltolás hozzárendeléssel kombinálva <<= a <<= b a = a << b Igen Igen R T::operator <<=(S b); R operator <<=(T a, S b);
Bitenkénti jobbra eltolás hozzárendeléssel kombinálva [4. megjegyzés] >>= a >>= b a = a >> b Igen Igen R T::operator >>=(S b); R operator >>=(T a, S b);

Operátorok mutatókkal és osztálytagokkal való munkához

Operátor Szintaxis Túlterhelhető C -ben végrehajtva Példa
T típusú tag Definíció az osztályon kívül
Hozzáférés egy tömbelemhez a[b] Igen Igen R T::operator [](S b);
n/a
Közvetett hivatkozás ("az objektum, amelyre egy ") mutatott *a Igen Igen R T::operator *(); R operator *(T a);
Link ("cím a ") &a Igen Igen R T::operator &(); R operator &(T a);
Hivatkozás egy struktúra tagjára (" az objektum b tagja, amelyre a " mutat) a->b Igen Igen R* T::operator ->();[5. megjegyzés]
n/a
Hivatkozás egy struktúra tagjára (" a objektum b tagja ") a.b Nem Igen n/a
A b által mutatott tag az a-val jelölt objektumban [6. megjegyzés] a->*b Igen Nem R T::operator ->*(S b); R operator ->*(T a, S b);
A b által mutatott tag az a objektumban a.*b Nem Nem n/a

Egyéb operátorok

Operátor Szintaxis Túlterhelhető C -ben végrehajtva Példa
T típusú tag Definíció az osztályon kívül
Functor a(a1, a2) Igen Igen R T::operator ()(S a1, U a2, ...); n/a
A vessző operátor a, b Igen Igen R T::operator ,(S b); R operator ,(T a, S b);
Terner feltételes működés a ? b : c Nem Igen n/a
Hatókör-kiterjesztés operátor a::b Nem Nem n/a
Egyéni literálok (bevezetve a C++11-ben) "a"_b Igen Nem n/a R operator "" _b(T a)
Méret (méret) sizeof(a)[7. megjegyzés]
sizeof(type)
Nem Igen n/a
Igazítás ( igazítás ) alignof(type)vagy [8. megjegyzés]_Alignof(type) Nem Igen n/a
Önelemzés typeid(a)
typeid(type)
Nem Nem n/a
Típusöntés (type) a Igen Igen T::operator R(); n/a
[9. megjegyzés]
Memóriakiosztás new type Igen Nem void* T::operator new(size_t x); void* operator new(size_t x);
Memóriakiosztás egy tömbhöz new type[n] Igen Nem void* T::operator new[](size_t x); void* operator new[](size_t x);
Memória felszabadítása delete a Igen Nem void T::operator delete(void* x); void operator delete(void* x);
Egy tömb által elfoglalt memória felszabadítása delete[] a Igen Nem void T::operator delete[](void* x); void operator delete[](void* x);

Megjegyzések:

  1. 1 2 A % operátor csak egész számokkal működik. Lebegőpontos számokhoz használja a () függvényt a " math.h " fájlból .fmod
  2. 1 2 Az előtag és az utótag (postfix) operátorok megkülönböztetésére egy használaton kívüli formális típusparaméter került hozzáadásra a postfix operátorokhoz . Ennek a paraméternek gyakran még nevet sem adnak.int
  3. 1 2 Az iostream könyvtárban a " " és a " " operátorok a streaming kimenettel és bemenettel dolgoznak.<<>>
  4. 1 2 A C99 szabvány szerint a negatív szám jobbra tolása implementáció által meghatározott viselkedés (lásd nem meghatározott viselkedés ). Sok fordító , köztük a gcc (lásd a 2019. szeptember 22-én a Wayback Machine -nél archivált dokumentációt ) alkalmazza az aritmetikai eltolást , de a szabvány nem tiltja a logikai eltolás megvalósítását . 
  5. A " " operátor visszatérési típusának olyan típusúnak kell lennie, amelyre az " " operátor vonatkozik , például mutatónak. Ha a " " típusú " ", és a " " osztály túlterheli a " " operátort , akkor a " " kifejezés kibővül a következőre: " ".operator->()->xCCoperator->()x->yx.operator->()->y
  6. Lásd a példát a Wayback Machine cikkében , archiválva : 2013. május 17. „ Intelligens mutatókezelő megvalósítása ”, Scott Myers , Dr. Dobb folyóirata , 1999. októberi szám. ->*
  7. Az operátort általában zárójelben írják. Ha az operandus egy változónév, a zárójelek nem kötelezőek. Ha az operandus típusnév, akkor a zárójelek megadása kötelező.sizeof
  8. A C++ nyelvi szabvány határozza meg a alignof. A szabványos C nyelvben egy hasonló operátort nevezünk _Alignof.
  9. Cast operátor esetén a visszatérési típus nincs kifejezetten megadva, mivel az megegyezik az operátor nevével.

Operátori elsőbbség

Ez a táblázat felsorolja az operátorok elsőbbségét és asszociativitását. A fenti (korábbi) táblázatban felsorolt ​​operátorok magasabb prioritásúak (értékelési elsőbbség). Egy kifejezés figyelembe vételekor a magasabb prioritású operátorok az alacsonyabb prioritású operátorok előtt kerülnek kiértékelésre. Ha ugyanabban a cellában több operátor van megadva, akkor ezeknek ugyanaz a prioritása, és az asszociativitás által meghatározott sorrendben kerülnek kiértékelésre. A kezelői prioritás nem változik túlterhelt állapotban.


Ez a prioritási táblázat a legtöbb esetben elegendő, a következő kivételekkel. A "?:" háromtagú operátor tartalmazhat "vessző" operátort vagy hozzárendelést a középső kifejezésben, de a fordító a " " kódot " "ként értelmezi , és nem értelmetlen " " kifejezésként. Így a és közötti kifejezést úgy kezeljük, mintha zárójelben lenne. a ? b, c : da ? (b, c) : d(a ? b), (c : d)?:

Prioritás Operátor Leírás Az asszociativitás
egy

Legmagasabb

:: Hatókör felbontás Nem
2 ++ Utótag növekménye Balról jobbra
-- Utótag csökkenése
() Funkcióhívás _
[] Egy tömbelem felvétele
. Elem kiválasztása hivatkozással
-> Elem kiválasztása mutató segítségével
typeid() RTTI (csak C++; lásd a típusazonosítót )
const_cast Típusöntés (C++) (lásd: Const cast )
dynamic_cast Típusöntés (C++) (lásd: dinamikus cast )
reinterpret_cast Szójáték (C++) (lásd reinterpret_cast )
static_cast Típusöntés (C++) (lásd statikus öntés )
3 ++ előtag növekménye Jobbról balra
-- előtag csökkenése
+ egységes plusz
- egységes mínusz
! Logikus NEM
~ Bitenként NEM
(type) Típusöntés
* Mutató dereferálása
& Objektum címének felvétele
sizeof Méret (méret)
new,new[] Dinamikus memóriafoglalás (C++)
delete,delete[] Dinamikus memória felosztása (C++)
négy .* Mutató a tagra (C++) Balról jobbra
->* Mutató a tagra (C++)
5 * Szorzás
/ Osztály
% Az osztás maradékának megszerzése
6 + Kiegészítés
- Kivonás
7 << Kis eltolás balra
>> Bit eltolás jobbra
nyolc < Kevésbé
<= Kisebb vagy egyenlő
> Több
>= Több vagy egyenlő
9 == Egyenlőség
!= Egyenlőtlenség
tíz & Bitenként ÉS (és)
tizenegy ^ Bitenkénti XOR (xor)
12 | Bitenként VAGY (vagy)
13 && logikus ÉS
tizennégy || Logikus VAGY
tizenöt ?: Terner feltételes működés Jobbról balra
= Feladat
+= Kiegészítés megbízással kombinálva
-= Kivonás hozzárendeléssel kombinálva
*= Szorzás hozzárendeléssel kombinálva
/= Megosztással egybekötve
%= Egy osztás maradékának kiszámítása, hozzárendeléssel kombinálva
<<= Bitenkénti bal eltolás hozzárendeléssel kombinálva
>>= Bitenkénti jobb eltolás hozzárendeléssel kombinálva
&= Bitenkénti „ÉS” hozzárendeléssel kombinálva
|= Bitenkénti "OR" hozzárendeléssel kombinálva
^= Bitenkénti kizárólagos VAGY (xor) hozzárendeléssel kombinálva
throw Throw Exception Operator (C++)
16 , A vessző operátor Balról jobbra

Leírás

A fordító egy precedenciatáblázat segítségével határozza meg az operátorok kiértékelésének sorrendjét.

  • Például ++x*3kétértelmű lenne minden elsőbbségi szabály nélkül. A táblázatból azt mondhatjuk, hogy x először a ++ operátorral van társítva , és csak azután a * operátorral , tehát a ++ operátor műveletétől függetlenül ez a művelet csak x -en van (és nem x*3). Így a kifejezés ekvivalens ( ++x, x*3).
  • Hasonlóképpen a kóddal, 3*x++ahol a táblázat azt írja ki, hogy a növekedés csak x -re vonatkozik, és nem 3*x. Funkcionálisan ez a kifejezés egyenértékű a ( )-vel, ha az ideiglenes változót tmp -ként fejezi ki .tmp=x, x++, tmp=3*tmp, tmp

Az operátorkötést a C és C++ szabványban a nyelv nyelvtana határozza meg, nem pedig egy táblázat. Ez konfliktust szülhet. Például C-ben a feltételes utasítás szintaxisa a következő:

logikai - VAGY - kifejezés ? kifejezés : feltételes - kifejezés

És C++-ban:

logikai - VAGY - kifejezés ? kifejezés : hozzárendelés - kifejezés

Emiatt a kifejezés:

e = a < d? a++ : a = d

eltérően fogják fel a két nyelven. C-ben a kifejezés szintaktikailag hibás, mert egy feltételes utasítás eredménye nem szolgálhat lvértékként (vagyis egy hozzárendelési utasítás bal oldala).

A C++ nyelvben a kifejezés érvényesként lesz értelmezve: [1]

e = ( a < d ? a ++ : ( a = d ))

A bitenkénti logikai operátorok elsőbbsége némileg nem intuitív [2] . Fogalmilag &, és |ugyanazok az aritmetikai operátorok, mint *és +rendre.

A kifejezés szintaktikailag kezelve van , de a kifejezés megegyezik a kifejezéssel . Emiatt gyakran szükséges a zárójelek használata az értékelés sorrendjének kifejezett megadásához. a & b == 7a & (b == 7)a + b == 7(a + b) == 7

Operátori szinonimák a C++ nyelvben

A C++ szabvány [3] digráfot határoz meg néhány operátorhoz:

Kétjegyű mássalhangzó Egyenértékű karakterlánc
és &&
bitand &
and_eq &=
vagy ||
bitor |
or_eq |=
xor ^
xor_eq ^=
nem !
not_eq !=
kompl ~

A digráfok ugyanúgy használhatók, mint az operátorok, ezek az operátorok szinonimája. Például a " " digráf használható a "bitenkénti ÉS" és a "get address" operátorok helyettesítésére, vagy a referenciatípusok meghatározásában. Így a „ ” kód egyenértékű a „ ” kóddal. bitandint bitand ref = n;int & ref = n;

Az ANSI/ISO C szabvány a felsorolt ​​digráfokat konstansként határozza meg #define(lásd az előfeldolgozót ). Az állandók a " " fejlécfájlban vannak meghatározva iso646.h. A C kompatibilitás érdekében a C++ szabvány egy " " dummy fejlécfájlt határoz meg ciso646.

Jegyzetek

  1. Valójában a C/C++ hármas operátornak ugyanaz a prioritása, mint a hozzárendelési operátoroknak? . verem túlcsordulás. Letöltve: 2019. szeptember 22. Az eredetiből archiválva : 2020. augusztus 6..
  2. Történelem (downlink) . Letöltve: 2013. január 11. Az eredetiből archiválva : 2013. június 22. 
  3. ISO/IEC JTC1/SC22/WG21 - C++ Szabványügyi Bizottság . ISO/IEC 14882:1998(E) A C++ programozási  nyelv . - International Group for the Standardization of the C++ Programming Language, 1998. - P. 40-41.

Linkek

  • A cikk archiválva 2019. február 26-án a Wayback Machine " C++ Operators" oldalán a cppreference.com webhelyen . 
  • Archivált : 2013. március 4. A Wayback Machine " Előtag és postfix operátorok C és C++ nyelven" című cikke az msdn.microsoft.com webhelyen . 
  • ISO/IEC 14882