Allmänna ämnen | ||||
Flödesstyrning | ||||
Villkorlig utförandet | ||||
|
||||
Iterationsinstruktioner (slingor) | ||||
intervall- |
||||
Hoppförklaringar | ||||
|
|
|||
Funktioner | ||||
Funktionsdeklaration | ||||
Deklaration av lambdafunktioner | ||||
inline specifiering |
||||
Specifikation av undantag (fram till C++20) | ||||
noexcept Specifikation (C++11) |
||||
Undantag | ||||
Namespaces | ||||
Typer | ||||
Specifiers | ||||
|
|
|||
Specifikationer för lagringstid | ||||
Initialisering | ||||
Uttryck | |||||||||
Alternativa representationer | |||||||||
Bokstavsord | |||||||||
Boolean – heltal – flyttal | |||||||||
tecken – sträng – nullptr (C++11) |
|||||||||
användar-definierad (C++11) | |||||||||
Utilities | |||||||||
Attribut (C++11) | |||||||||
Typer | |||||||||
typedef deklaration |
|||||||||
Deklaration av typalias (C++11) | |||||||||
Casts | |||||||||
Implicita konverteringar – Explicita konverteringar | |||||||||
static_cast – dynamic_cast |
|||||||||
const_cast – – – |
|||||||||
const_cast – reinterpret_cast |
|||||||||
Minnestilldelning | |||||||||
Klasser | |||||||||
Klass-specifika funktionsegenskaper | |||||||||
Virtuell funktion override-specifikation (C++11) final-specifikation (C++11) |
|
||||||||
Särskilda medlemsfunktioner | |||||||||
Kopiering
Flyttning (C++11) Destructor |
|||||||||
Mallar | |||||||||
Specialisering av mallar Parametrarpaket (C++11) |
|||||||||
Diverse | |||||||||
Operatörsnamn | Syntax | Överladdningsbart | Prototypexempel (för klassen T) | |
---|---|---|---|---|
Inom klassdefinition | Utanför klassdefinition | |||
unärt plus | +a |
Ja | T T T::operator+() const; | T operator+(const T &a); |
unary minus | -a |
Ja | T T::operator-() const; | T operator-(const T &a); |
addition | a + b |
Ja | T T::operator+(const T2 &b) const; | T operator+(const T &a, const T2 &b); |
subtraktion | a - b |
Ja | T T::operator-(const T2 &b) const; | T operator-(const T &a, const T2 &b); |
multiplikation | a * b |
Ja | T T::operator*(const T2 &b) const; | T operator*(const T &a, const T2 &b); |
division | a / b |
Ja | T T::operator/(const T2 &b) const; | T operator/(const T &a, const T2 &b); |
modulo | a % b |
Ja | T T::operator%(const T2 &b) const; | T operator%(const T &a, const T2 &b); |
bitvis NOT | ~a |
Ja | T T::operator~() const; | T operator~(const T &a); |
bitvis AND | a & b |
Ja | T T::operator&(const T2 &b) const; | T operator&(const T &a, const T2 &b); |
bitvis OR | a | b |
Ja | T T::operator|(const T2 &b) const; | T operator|(const T &a, const T2 &b); |
bitvis XOR | a ^ b |
Ja | T T::operator^(const T2 &b) const; | T operator^(const T &a, const T2 &b); |
bitvis vänsterförskjutning | a << b |
Ja | T T::operator<<(const T2 &b) const; | T operator<<(const T &a, const T2 &b); |
bitvis högerförskjutning | a >> b |
Ja | T T::operator>>(const T2 &b) const; | T operator>>(const T &a, const T2 &b); |
Anmärkningar
|
Innehåll
- 1 Förklaring
- 1.1 Konverteringar
- 1.2 Överströmningar
- 1.3 Flyttpunktsmiljö
- 1.4 Flyttpunktskontraktion
- 1.5 Unära aritmetiska operatorer
- 1.6 Additionsoperatorer
- 1.7 Multiplikationsoperatorer
- 1.8 Bitvisa logiska operatorer
- 1.9 Bitvisa skiftoperatörer
- 2 Standardbibliotek
- 2.1 Unära aritmetiska operatörer
- 2.2 Additiva operatörer
- 2.3 Multiplikativa operatörer
- 2.4 Bitvisa logiska operatörer
- 2.5 Bitvisa skiftoperatörer
- 2.6 Stream insertion/extraction operators
- 3 Felrapporter
- 4 Se även
Förklaring
Alla aritmetiska operatörer beräknar resultatet av en specifik aritmetisk operation och returnerar dess resultat. Argumenten ändras inte.
Konverteringar
Om den operand som överlämnats till en aritmetisk operatör är av typen integral eller unscoped enumeration, genomgår operanden före någon annan åtgärd (men efter lvärde-till-r-värde-konvertering, i förekommande fall) en integralbefordran. Om en operand har en array- eller funktionstyp tillämpas array-till-pointer- och funktions-till-pointer-konverteringar.
För de binära operatörerna (utom shifts), om de promoverade operanderna har olika typer, tillämpas ytterligare en uppsättning implicita konverteringar, som är kända som vanliga aritmetiska konverteringar med målet att producera den gemensamma typen (som också är tillgänglig via std::common_type type trait). Om en operand före en integral promotion är av uppräkningstyp och den andra operanden är av en flyttalstyp eller en annan uppräkningstyp, är detta beteende föråldrat. (sedan C++20)
- Om någon av operanderna har scoped enumerationstyp utförs ingen konvertering: Den andra operanden och returtypen måste ha samma typ
- Om någon av operanderna är long double konverteras den andra operanden till long double
- Om någon av operanderna är double konverteras den andra operanden till double
- Annars, Om någon av operanderna är float konverteras den andra operandern till float
- Annars har operandern heltalstyp (eftersom bool, char, char8_t, char16_t, char32_t, wchar_t och unscoped enumeration har främjats vid denna tidpunkt) och integralkonverteringar tillämpas för att producera den gemensamma typen, enligt följande:
- Om båda operanderna är signerade eller om båda är osignerade, konverteras den operand som har lägst konverteringsrang till den operand som har högst konverteringsrang för heltal
- Om den osignerade operandens konverteringsrang är större än eller lika med konverteringsrangen för den signerade operanden, konverteras den signerade operanden till den osignerade operandens typ.
- Om den signerade operandens typ kan representera alla värden för den osignerade operandens typ, konverteras den osignerade operandens typ till den signerade operandens typ
- I annat fall konverteras båda operanderna till den osignerade motsvarigheten till den signerade operandens typ.
Ovanstående konverteringsranking ökar i ordningen bool, signerad char, short, int, long, long long long. Rangordningen för varje osignerad typ är lika med rangordningen för motsvarande signerad typ. Rangordningen av char är lika med rangordningen av signed char och unsigned char. Rangordningen för char8_t, char16_t, char32_t och wchar_t är lika med rangordningen för deras underliggande typer.
Överflöden
Aritmetik med obetyda heltal utförs alltid modulo 2n
där n är antalet bitar i det specifika heltalet. Exempelvis för unsigned int ger addition av ett till UINT_MAX 0, och subtraktion av ett från 0 ger UINT_MAX.
När en aritmetisk operation för signerade heltal går över (resultatet får inte plats i resultattypen) är beteendet odefinierat, – de möjliga manifestationerna av en sådan operation är bland annat:
- den sveper runt enligt reglerna för representationen (typiskt 2:s komplement),
- den fastnar – på vissa plattformar eller på grund av kompileralternativ (t.ex.
-ftrapv
i GCC och Clang), - den mättas till minimalt eller maximalt värde (på många DSP:er),
- den optimeras helt ut av kompilatorn.
Flyttpunktsmiljö
Om #pragma STDC FENV_ACCESS stöds och är satt till ON
, alla aritmetiska operatorer för flytande punkter lyder den aktuella avrundningsriktningen för flytande punkter och rapporterar aritmetiska fel för flytande punkter enligt vad som anges i math_errhandling om de inte är en del av en statisk initialiserare (i vilket fall undantag för flytande punkter inte tas upp och avrundningsläget är till närmaste)
Kontraktion av flytande punkter
Om inte #pragma STDC FP_CONTRACT stöds och är satt till OFF
, kan all aritmetik med flytande punkter utföras som om mellanresultaten har oändlig räckvidd och precision, dvs. optimeringar som utelämnar avrundningsfel och undantag för flytande punkter är tillåtna. C++ tillåter till exempel genomförandet av (x*y) + z med en enda sammanslagen multiplikations-add-instruktion eller optimering av a = x*x*x*x*x; som tmp = x *x; a = tmp*tmp.
Oavsett kontraktsskrivning kan mellanliggande resultat av aritmetik med flyttal ha ett intervall och en precision som skiljer sig från det som anges av dess typ, se FLT_EVAL_METHOD
Formellt sett ger C++-standarden ingen garanti för noggrannheten hos flyttaloperationer.
Unära aritmetiska operatorer
De unära aritmetiska operatoruttrycken har formen
+ uttryck |
. (1) | ||||||||
- uttryck |
(2) | ||||||||
Den inbyggda unära plus-operatorn returnerar värdet av sin operand. Den enda situation där den inte är ett no-op är när operanden har integral typ eller unscoped uppräkningstyp, som ändras av integral promotion, t.ex. konverterar den char till int eller om operanden är föremål för lvärde-till-r-värde, array-till-pointer eller funktion-till-pointer konvertering.
Den inbyggda unära minusoperatorn beräknar negativet av sin promoverade operand. För otecknat a
är värdet av -a
2b
-a, där b
är antalet bitar efter befordran.
I överbelastningsupplösning mot användardefinierade operatörer deltar följande funktionssignaturer i överbelastningsupplösning för varje promoverad aritmetisk typ A
och för varje typ T
:
#include <iostream>int main(){ char c = 0x6a; int n1 = 1; unsigned char n2 = 1; unsigned int n3 = 1; std::cout << "char: " << c << " int: " << +c << '\n' << "-1, where 1 is signed: " << -n1 << '\n' << "-1, where 1 is unsigned char: " << -n2 << '\n' << "-1, where 1 is unsigned int: " << -n3 << '\n'; char a; std::cout << "size of array: " << sizeof a << '\n' << "size of pointer: " << sizeof +a << '\n';}
Output:
char: j int: 106-1, where 1 is signed: -1-1, where 1 is unsigned char: -1-1, where 1 is unsigned int: 4294967295size of array: 3size of pointer: 8
Additiva operatorer
De binära additiva aritmetiska operatoruttrycken har formen
lhs + rhs |
(1) | ||||||||
lhs - rhs |
(2) | ||||||||
- båda har aritmetisk typ eller en uppräkningstyp utan scope. I detta fall utförs de vanliga aritmetiska konverteringarna på båda operanderna och bestämmer resultatets typ.
- Den ena är en pekare till fullständigt definierad objekttyp, den andra har integral- eller unscoped enumerationstyp. I detta fall har resultattypen pekarens typ.
- Båda har aritmetisk eller unscoped enumerationstyp. I detta fall utförs de vanliga aritmetiska konverteringarna på båda operanderna och bestämmer resultatets typ.
- lhs är en pekare till fullständigt definierad objekttyp, rhs har integral- eller unscoped uppräkningstyp. I detta fall har resultattypen pekarens typ.
- båda är pekare till samma fullständigt definierade objekttyper, utan hänsyn till cv-kvalificerare. I det här fallet är resultattypen std::ptrdiff_t.
Med operander av aritmetisk typ eller uppräkningstyp är resultatet av binärt plus summan av operanderna (efter sedvanliga aritmetiska konverteringar) och resultatet av den binära minusoperatorn är resultatet av subtraheringen av den andra operanden från den första (efter sedvanliga aritmetiska konverteringar), förutom att om typen stöder IEEE-flytande-punktsaritmetik (se std::numeric_limits::is_iec559),
- om en operand är NaN är resultatet NaN
- oändlighet minus oändlighet är NaN och FE_INVALID tas upp
- oändlighet plus den negativa oändligheten är NaN och FE_INVALID tas upp
Om någon av operanderna är en pekare gäller följande regler:
- En pekare till ett objekt som inte är en array behandlas som en pekare till det första elementet i en array med storlek 1.
- Om pekaren
P
pekar på deti
:e elementet i en array är uttryckenP+n
,n+P
ochP-n
pekare av samma typ som pekar på deti+n
:e,i+n
:e respektivei-n
:e elementet i samma array. Resultatet av pekartillägget kan också vara en pekare som pekar en gång efter slutet (dvs. pekarenP
så att uttrycketP-1
pekar på det sista elementet i matrisen). Alla andra situationer (det vill säga försök att generera en pekare som inte pekar på ett element i samma array eller ett efter slutet) åberopar odefinierat beteende. - Om pekaren
P
pekar på deti
:e elementet i en array, och pekarenQ
pekar på detj
:e elementet i samma array, har uttrycketP-Q
värdet i-j, om värdet ryms i std::ptrdiff_t. Båda operanderna måste peka på elementen i samma array (eller ett efter slutet), annars är beteendet odefinierat. Om resultatet inte passar in i std::ptrdiff_t är beteendet odefinierat. - I vilket fall som helst, om den typ som pekas på skiljer sig från arrayelementtypen, utan hänsyn till cv-kvalifikationer, på varje nivå om elementen i sig är pekare, är beteendet för pekaritmetik odefinierat. I synnerhet är pekarräkning med pekare till bas, som pekar på ett element i en array av härledda objekt, odefinierad.
- Om värdet 0 adderas eller subtraheras från en pekare är resultatet pekaren, oförändrad. Om två pekare pekar på samma objekt eller båda har passerat slutet av samma array, eller båda är nollpekare, är resultatet av subtraktionen lika med (std::ptrdiff_t)0.
Dessa aritmetiska pekaroperatorer gör det möjligt för pekare att uppfylla kraven för LegacyRandomAccessIterator.
I överbelastningsupplösning mot användardefinierade operatörer deltar följande funktionssignaturer i överbelastningsupplösningen för varje par av främjade aritmetiska typer L
och R
och för varje objekttyp T
:
där LR
är resultatet av vanlig aritmetiska omvandlingar av L
och R
#include <iostream>int main(){ char c = 2; unsigned int un = 2; int n = -10; std::cout << " 2 + (-10), where 2 is a char = " << c + n << '\n' << " 2 + (-10), where 2 is unsigned = " << un + n << '\n' << " -10 - 2.12 = " << n - 2.12 << '\n'; char a = {'a', 'b', 'c', 'd'}; char* p = &a; std::cout << "Pointer addition examples: " << *p << *(p + 2) << *(2 + p) << *(p - 1) << '\n'; char* p2 = &a; std::cout << "Pointer difference: " << p2 - p << '\n';}
Output:
2 + (-10), where 2 is a char = -8 2 + (-10), where 2 is unsigned = 4294967288 -10 - 2.12 = -12.12Pointer addition examples: bddaPointer difference: 3
Multiplikativa operatörer
De binära multiplikativa aritmetiska operatoruttrycken har formen
lhs * rhs |
(1) | ||||||||
lhs / rhs |
(2) | ||||||||
lhs % rhs |
(3) | ||||||||
För alla tre operatorer utförs de vanliga aritmetiska konverteringarna på båda operanderna och bestämmer resultatets typ.
Den binära operatören * utför multiplikation av sina operander (efter sedvanliga aritmetiska konverteringar), förutom att, för multiplikation med flyttal,
- multiplikation av ett NaN med ett valfritt tal ger NaN
- multiplikation av oändligheten med noll ger NaN och FE_INVALID tas upp
Den binära operatören / dividerar den första operanden med den andra (efter sedvanliga aritmetiska omvandlingar).
För integrala operander ger den den algebraiska kvoten.
Kvoten avrundas i implementationsdefinierad riktning. |
(fram till C++11) |
Kotienten trunkeras mot noll (bråkdelen kastas bort). |
(sedan C++11) |
Om den andra operanden är noll är beteendet odefinierat, förutom att om division med flyttal äger rum och typen stöder IEEE-flytalsaritmetik (se std::numeric_limits::is_iec559), då:
- om den ena operanden är NaN, är resultatet NaN
- genom att dividera ett tal som inte är noll med ±0.0 ger den korrekt signerade oändligheten och FE_DIVBYZERO uppstår
- att dividera 0,0 med 0,0 ger NaN och FE_INVALID uppstår
Den binära operatorn % ger återstoden av heltalsdivisionen av den första operanden med den andra (efter sedvanliga aritmetiska konverteringar; observera att operandtyperna måste vara integrala typer). Om kvoten a/b
kan representeras i resultattypen är (a/b)*b + a%b == a. Om den andra operanden är noll är beteendet odefinierat. Om kvoten a/b
inte kan representeras i resultattypen är beteendet för både a/b
och a%b
odefinierat (det betyder att INT_MIN%-1 är odefinierat på 2:s komplementsystem)
Anm.: Fram till C++11, om en eller båda operanderna till den binära operatören % var negativa, var tecknet på återstoden implementationsdefinierat, eftersom det beror på avrundningsriktningen för heltalsdivision. Funktionen std::div gav ett väldefinierat beteende i det fallet.
Anm.: För rest för flyttal, se std::remainder och std::fmod.
I överbelastningsupplösning mot användardefinierade operatörer deltar följande funktionssignaturer i överbelastningsupplösningen för varje par av de främjade aritmetiska typerna LA
och RA
och för varje par av de främjade integrala typerna LI
och RI
:
där LRx
är resultatet av vanlig aritmetiska omvandlingar av Lx
och Rx
#include <iostream>int main(){ char c = 2; unsigned int un = 2; int n = -10; std::cout << "2 * (-10), where 2 is a char = " << c * n << '\n' << "2 * (-10), where 2 is unsigned = " << un * n << '\n' << "-10 / 2.12 = " << n / 2.12 << '\n' << "-10 / 21 = " << n / 21 << '\n' << "-10 % 21 = " << n % 21 << '\n';}
Output:
2 * (-10), where 2 is a char = -202 * (-10), where 2 is unsigned = 4294967276-10 / 2.12 = -4.71698-10 / 21 = 0-10 % 21 = -10
Bitvisa logiska operatörer
De bitvisa aritmetiska operatoruttrycken har formen
~ rhs |
(1) | ||||||||
lhs & rhs |
(2) | ||||||||
lhs | rhs |
(3) | ||||||||
lhs ^ rhs |
(4) | ||||||||
Resultatet av operator~ är det bitvisa NOT-värdet (ett komplement) av argumentet (efter befordran). Resultatet av operator& är det bitvisa AND-värdet av operanderna (efter vanliga aritmetiska konverteringar). Resultatet av operator| är det bitvisa OR-värdet av operanderna (efter vanliga aritmetiska omvandlingar). Resultatet av operator^ är det bitvisa XOR-värdet av operanderna (efter vanliga aritmetiska omvandlingar)
I överbelastningsupplösning mot användardefinierade operatörer deltar följande funktionssignaturer i överbelastningsupplösningen för varje par av främjade integraltyper L
och R
:
där LR
är resultatet av vanlig aritmetiska omvandlingar av L
och R
#include <iostream>int main(){ std::cout << std::hex << std::showbase; uint16_t mask = 0x00f0; uint32_t a = 0x12345678; std::cout << "Value: " << a << " mask: " << mask << '\n' << "Setting bits: " << (a | mask) << '\n' << "Clearing bits: " << (a & ~mask) << '\n' << "Selecting bits: " << (a & mask) << '\n';}
Output:
Value: 0x12345678 mask: 0xf0Setting bits: 0x123456f8Clearing bits: 0x12345608Selecting bits: 0x70
Bitvisa skiftoperatorer
De bitvisa skiftoperatoruttrycken har formen
lhs << rhs |
(1) | ||||||||
lhs >> rhs |
(2) | ||||||||
Returtypen är typen för den vänstra operanden efter integralpromotioner.
För unsigned För signerade och icke-negativa För negativa För osignerat För negativt |
(fram till C++20) |
Värdet av Värdet av |
(sedan C++20) |
I vilket fall som helst är beteendet odefinierat om värdet av den högra operandan är negativt eller är större än eller lika med antalet bitar i den promoverade vänstra operanden.
I överbelastningsupplösning mot användardefinierade operatorer deltar följande funktionssignaturer i överbelastningsupplösningen för varje par av främjade integraltyper L
och R
:
#include <iostream>enum {ONE=1, TWO=2};int main(){ std::cout << std::hex << std::showbase; char c = 0x10; unsigned long long ull = 0x123; std::cout << "0x123 << 1 = " << (ull << 1) << '\n' << "0x123 << 63 = " << (ull << 63) << '\n' // overflow in unsigned << "0x10 << 10 = " << (c << 10) << '\n'; // char is promoted to int long long ll = -1000; std::cout << std::dec << "-1000 >> 1 = " << (ll >> ONE) << '\n';}
Output:
0x123 << 1 = 0x2460x123 << 63 = 0x80000000000000000x10 << 10 = 0x4000-1000 >> 1 = -500
Standardbibliotek
Aritmetiska operatorer är överladdade för många typer i standardbiblioteket.
Aritmetiska operatorer för unary
(offentlig medlemsfunktion i
std::chrono::duration<Rep,Period>
)
(funktionsmall)
(offentlig medlemsfunktion i
std::valarray<T>
) Additionsoperatorer
(funktionsmall)
(funktionsmall)
year_month_day
och några antal år eller månader (offentlig medlemsfunktion i
std::chrono::year_month_day
)
(funktionsmall)
(offentlig medlemsfunktion i
std::reverse_iterator<Iter>
)
(public member function of
std::move_iterator<Iter>
)
(funktionsmall)
(funktionsmall)
Multiplikativa operatorer
(funktionsmall)
(funktionsmall)
(funktionsmall)
Bitvisa logiska operatörer
(public member function of
std::bitset<N>
)
(funktionsmall)
(public member function of
std::valarray<T>
)
(funktionsmall)
Bitvisa skiftoperatörer
(funktionsmall)
(offentlig medlemsfunktion i
std::bitset<N>
) Operatorer för insättning/utvinning av strömmar
I standardbiblioteket är bitvisa förskjutningsoperatörer vanligen överbelastade med I/O stream (std::ios_base& eller en av de klasser som härletts från den) som både vänster operand och returtyp. Sådana operatörer kallas stream insertion och stream extraction operators:
(public member function of
std::basic_istream<CharT,Traits>
)
(funktionsmall)
(public member function of
std::basic_ostream<CharT,Traits>
)
(funktionsmall)
(funktionsmall)
(funktionsmall)
(funktionsmall)
(funktionsmall)
(funktionsmall)
Defektrapporter
Följande beteendeförändrande defektrapporter har tillämpats retroaktivt på tidigare publicerade C++-standarder.
DR | Tillämpat på | Beteende som publicerat | Korrekt beteende |
---|---|---|---|
CWG 1457 | C++98 | att flytta den vänstra 1 biten av ett positivt signerat värde in i teckenbiten var UB |
gjort väl.definierad |
Se även
Operator precedence
Operator overloading
Vanliga operatörer | ||||||
---|---|---|---|---|---|---|
assignment | inkrement dekrement |
aritmetisk | logisk | jämförelse | member access |
annan |
a = b |
++a –a a++ a– |
+a |
!a a && b a || b |
a == b |
a |
a(…) |
Specialoperatorer | ||||||
static_cast konverterar en typ till en annan relaterad typ |