Namespaces
Variants

operator overloading

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Personnalise les opérateurs C++ pour les opérandes de types définis par l'utilisateur.

Table des matières

Syntaxe

Fonctions d'opérateur sont des fonctions avec des noms de fonction spéciaux :

operator op (1)
operator new
operator new []
(2)
operator delete
operator delete []
(3)
operator co_await (4) (depuis C++20)
op - l'un des opérateurs suivants : + - * / % ^ & | ~ ! = < > + = - = * = / = % = ^ = & = | = << >> >>= <<= == ! = <= >= <=> (depuis C++20) && || ++ -- , - > * - > ( ) [ ]
1) Un opérateur de ponctuation surchargé.
4) Un opérateur co_await surchargé pour utilisation dans les co_await expressions .

Les comportements des opérateurs non-ponctuation sont décrits dans leurs propres pages respectives. Sauf indication contraire, la description restante dans cette page ne s'applique pas à ces fonctions.

Explication

Lorsqu'un opérateur apparaît dans une expression , et qu'au moins un de ses opérandes a un type classe ou un type énumération , alors la résolution de surcharge est utilisée pour déterminer la fonction définie par l'utilisateur à appeler parmi toutes les fonctions dont les signatures correspondent à ce qui suit :

Expression En tant que fonction membre En tant que fonction non-membre Exemple
@a (a).operator@ ( ) operator@ (a) ! std:: cin appelle std:: cin . operator ! ( )
a@b (a).operator@ (b) operator@ (a, b) std:: cout << 42 appelle std:: cout . operator << ( 42 )
a=b (a).operator= (b) ne peut pas être non-membre Étant donné std:: string s ; , s = "abc" ; appelle s. operator = ( "abc" )
a(b...) (a).operator()(b...) ne peut pas être non-membre Étant donné std:: random_device r ; , auto n = r ( ) ; appelle r. operator ( ) ( )
a[b...] (a).operator[](b...) ne peut pas être non-membre Étant donné std:: map < int , int > m ; , m [ 1 ] = 2 ; appelle m. operator [ ] ( 1 )
a-> (a).operator->( ) ne peut pas être non-membre Étant donné std:: unique_ptr < S > p ; , p - > bar ( ) appelle p. operator - > ( )
a@ (a).operator@ (0) operator@ (a, 0) Étant donné std:: vector < int > :: iterator i ; , i ++ appelle i. operator ++ ( 0 )

Dans ce tableau, @ est un espace réservé représentant tous les opérateurs correspondants : tous les opérateurs préfixes dans @a, tous les opérateurs postfixes autres que -> dans a@, tous les opérateurs infixes autres que = dans a@b.

De plus, pour les opérateurs de comparaison == , ! = , < , > , <= , >= , <=> , la résolution de surcharge considère également les candidats réécrits operator == ou operator <=> .

(depuis C++20)

Les opérateurs surchargés (mais pas les opérateurs intégrés) peuvent être appelés en utilisant la notation de fonction :

std::string str = "Bonjour, ";
str.operator+=("monde");                      // identique à str += "monde";
operator<<(operator<<(std::cout, str), '\n'); // identique à std::cout << str << '\n';
                                              // (depuis C++17) sauf pour le séquencement

Opérateurs surchargés statiques

Les opérateurs surchargés qui sont des fonctions membres peuvent être déclarés static . Cependant, ceci est uniquement autorisé pour operator ( ) et operator [ ] .

Ces opérateurs peuvent être appelés en utilisant la notation de fonction. Cependant, lorsque ces opérateurs apparaissent dans des expressions, ils nécessitent toujours un objet de type classe.

struct SwapThem
{
    template<typename T>
    static void operator()(T& lhs, T& rhs) 
    {
        std::ranges::swap(lhs, rhs);
    }
    template<typename T>
    static void operator[](T& lhs, T& rhs)
    {
        std::ranges::swap(lhs, rhs);
    } 
};
inline constexpr SwapThem swap_them{};
void foo()
{
    int a = 1, b = 2;
    swap_them(a, b); // OK
    swap_them[a, b]; // OK
    SwapThem{}(a, b); // OK
    SwapThem{}[a, b]; // OK
    SwapThem::operator()(a, b); // OK
    SwapThem::operator[](a, b); // OK
    SwapThem(a, b); // error, invalid construction
    SwapThem[a, b]; // error
}
(depuis C++23)

Restrictions

  • Une fonction d'opérateur doit avoir au moins un paramètre de fonction ou un paramètre d'objet implicite dont le type est une classe, une référence à une classe, une énumération, ou une référence à une énumération.
  • Les opérateurs :: (résolution de portée), . (accès membre), .* (accès membre via pointeur sur membre), et ?: (conditionnel ternaire) ne peuvent pas être surchargés.
  • De nouveaux opérateurs tels que ** , <> , ou &| ne peuvent pas être créés.
  • Il n'est pas possible de modifier la priorité, le groupement ou le nombre d'opérandes des opérateurs.
  • La surcharge de l'opérateur -> doit soit retourner un pointeur brut, soit retourner un objet (par référence ou par valeur) pour lequel l'opérateur -> est à son tour surchargé.
  • Les surcharges des opérateurs && et || perdent l'évaluation en court-circuit.
  • && , || , et , perdent leurs propriétés spéciales de séquencement lorsqu'ils sont surchargés et se comportent comme des appels de fonction réguliers, même lorsqu'ils sont utilisés sans notation d'appel de fonction.
(jusqu'à C++17)

Implémentations canoniques

En dehors des restrictions ci-dessus, le langage n'impose aucune autre contrainte sur ce que font les opérateurs surchargés, ou sur le type de retour (il ne participe pas à la résolution de surcharge), mais en général, les opérateurs surchargés sont censés se comporter de manière aussi similaire que possible aux opérateurs intégrés : operator + est censé additionner, plutôt que multiplier ses arguments, operator = est censé assigner, etc. Les opérateurs associés sont censés se comporter de manière similaire ( operator + et operator + = effectuent la même opération de type addition). Les types de retour sont limités par les expressions dans lesquelles l'opérateur est censé être utilisé : par exemple, les opérateurs d'assignement retournent par référence pour permettre d'écrire a = b = c = d , car les opérateurs intégrés le permettent.

Les opérateurs couramment surchargés ont les formes typiques et canoniques suivantes : [1]

Opérateur d'affectation

L'opérateur d'assignation operator = possède des propriétés spéciales : voir l'assignation de copie et l'assignation de déplacement pour plus de détails.

L'opérateur canonique de copie par assignation est censé être sûr en cas d'auto-assignation , et retourner le lhs par référence :

// assignation de copie
T& operator=(const T& other)
{
    // Protection contre l'auto-assignation
    if (this == &other)
        return *this;
    // suppose que *this gère une ressource réutilisable, telle qu'un tampon alloué sur le tas mArray
    if (size != other.size)           // la ressource dans *this ne peut pas être réutilisée
    {
        temp = new int[other.size];   // alloue la ressource, si exception, ne fait rien
        delete[] mArray;              // libère la ressource dans *this
        mArray = temp;
        size = other.size;
    }
    std::copy(other.mArray, other.mArray + other.size, mArray);
    return *this;
}

L'assignation de déplacement canonique est censée laisser l'objet source dans un état valide (c'est-à-dire un état où les invariants de classe sont préservés), et soit ne rien faire soit au moins laisser l'objet dans un état valide en cas d'auto-assignation, et retourner le lhs par référence non-const, et être noexcept :

// move assignment
T& operator=(T&& other) noexcept
{
    // Guard self assignment
    if (this == &other)
        return *this; // delete[]/size=0 would also be ok
    delete[] mArray;                               // release resource in *this
    mArray = std::exchange(other.mArray, nullptr); // leave other in valid state
    size = std::exchange(other.size, 0);
    return *this;
}
(depuis C++11)

Dans les situations où l'affectation par copie ne peut pas bénéficier de la réutilisation des ressources (elle ne gère pas de tableau alloué sur le tas et n'a pas de membre (éventuellement transitif) qui le fait, tel qu'un membre std::vector ou std::string ), il existe un raccourci pratique populaire : l'opérateur d'affectation par copie-et-échange, qui prend son paramètre par valeur (fonctionnant ainsi à la fois comme affectation par copie et par déplacement selon la catégorie de valeur de l'argument), échange avec le paramètre, et laisse le destructeur le nettoyer.

// assignation par copie (idiome copy-and-swap)
T& T::operator=(T other) noexcept // appelle le constructeur de copie ou de déplacement pour construire other
{
    std::swap(size, other.size); // échange les ressources entre *this et other
    std::swap(mArray, other.mArray);
    return *this;
} // le destructeur de other est appelé pour libérer les ressources précédemment gérées par *this

Ce formulaire fournit automatiquement strong exception guarantee , mais interdit la réutilisation des ressources.

Extraction et insertion de flux

Les surcharges de operator>> et operator<< qui prennent un std:: istream & ou un std:: ostream & comme argument gauche sont appelées opérateurs d'insertion et d'extraction. Comme elles prennent le type défini par l'utilisateur comme argument droit ( b dans a @ b ), elles doivent être implémentées comme fonctions non-membres.

std::ostream& operator<<(std::ostream& os, const T& obj)
{
    // écrire obj dans le flux
    return os;
}
std::istream& operator>>(std::istream& is, T& obj)
{
    // lire obj depuis le flux
    if (/* T n'a pas pu être construit */)
        is.setstate(std::ios::failbit);
    return is;
}

Ces opérateurs sont parfois implémentés comme friend functions .

Opérateur d'appel de fonction

Lorsqu'une classe définie par l'utilisateur surcharge l'opérateur d'appel de fonction operator ( ) , elle devient un type FunctionObject .

Un objet de ce type peut être utilisé dans une expression d'appel de fonction :

// Un objet de ce type représente une fonction linéaire d'une variable a * x + b.
struct Linear
{
    double a, b;
    double operator()(double x) const
    {
        return a * x + b;
    }
};
int main()
{
    Linear f{2, 1};  // Représente la fonction 2x + 1.
    Linear g{-1, 0}; // Représente la fonction -x.
    // f et g sont des objets qui peuvent être utilisés comme une fonction.
    double f_0 = f(0);
    double f_1 = f(1);
    double g_0 = g(0);
}

De nombreuses algorithmes standards de la bibliothèque acceptent des FunctionObject s pour personnaliser leur comportement. Il n'existe pas de formes canoniques particulièrement notables pour l' operator ( ) , mais pour illustrer son utilisation :

#include <algorithm>
#include <iostream>
#include <vector>
struct Sum
{
    int sum = 0;
    void operator()(int n) { sum += n; }
};
int main()
{
    std::vector<int> v = {1, 2, 3, 4, 5};
    Sum s = std::for_each(v.begin(), v.end(), Sum());
    std::cout << "The sum is " << s.sum << '\n';
}

Sortie :

The sum is 15

Incrément et décrément

Lorsque l'opérateur d'incrémentation ou de décrémentation postfixé apparaît dans une expression, la fonction définie par l'utilisateur correspondante ( operator ++ ou operator -- ) est appelée avec un argument entier 0 . Typiquement, elle est déclarée comme T operator ++ ( int ) ou T operator -- ( int ) , où l'argument est ignoré. Les opérateurs d'incrémentation et de décrémentation postfixés sont généralement implémentés en fonction des versions préfixées :

struct X
{
    // incrémentation préfixe
    X& operator++()
    {
        // l'incrémentation réelle a lieu ici
        return *this; // retourne la nouvelle valeur par référence
    }
    // incrémentation postfixe
    X operator++(int)
    {
        X old = *this; // copie l'ancienne valeur
        operator++();  // incrémentation préfixe
        return old;    // retourne l'ancienne valeur
    }
    // décrémentation préfixe
    X& operator--()
    {
        // la décrémentation réelle a lieu ici
        return *this; // retourne la nouvelle valeur par référence
    }
    // décrémentation postfixe
    X operator--(int)
    {
        X old = *this; // copie l'ancienne valeur
        operator--();  // décrémentation préfixe
        return old;    // retourne l'ancienne valeur
    }
};

Bien que les implémentations canoniques des opérateurs de pré-incrément et de pré-décrément retournent par référence, comme pour toute surcharge d'opérateur, le type de retour est défini par l'utilisateur ; par exemple, les surcharges de ces opérateurs pour std::atomic retournent par valeur.

Opérateurs arithmétiques binaires

Les opérateurs binaires sont généralement implémentés en tant que non-membres pour préserver la symétrie (par exemple, lors de l'addition d'un nombre complexe et d'un entier, si operator + est une fonction membre du type complexe, alors seul complex + integer serait compilé, et non integer + complex ). Puisque pour chaque opérateur arithmétique binaire il existe un opérateur d'affectation composé correspondant, les formes canoniques des opérateurs binaires sont implémentées en utilisant leurs affectations composées :

class X
{
public:
    X& operator+=(const X& rhs) // assignation composée (n'a pas besoin d'être membre,
    {                           // mais l'est souvent, pour modifier les membres privés)
        /* l'addition de rhs à *this a lieu ici */
        return *this; // retourne le résultat par référence
    }
    // les fonctions amies définies dans le corps de la classe sont inline et cachées de la recherche non-ADL
    friend X operator+(X lhs,        // passer lhs par valeur aide à optimiser les chaînes a+b+c
                       const X& rhs) // sinon, les deux paramètres peuvent être des références constantes
    {
        lhs += rhs; // réutilise l'assignation composée
        return lhs; // retourne le résultat par valeur (utilise le constructeur de déplacement)
    }
};

Opérateurs de comparaison

Les algorithmes de la bibliothèque standard tels que std::sort et les conteneurs tels que std::set s'attendent à ce que operator < soit défini, par défaut, pour les types fournis par l'utilisateur, et s'attendent à ce qu'il implémente un ordre strict faible (satisfaisant ainsi les exigences Compare ). Une manière idiomatique d'implémenter un ordre strict faible pour une structure est d'utiliser la comparaison lexicographique fournie par std::tie :

struct Record
{
    std::string name;
    unsigned int floor;
    double weight;
    friend bool operator<(const Record& l, const Record& r)
    {
        return std::tie(l.name, l.floor, l.weight)
             < std::tie(r.name, r.floor, r.weight); // conserver le même ordre
    }
};

En général, une fois que operator < est fourni, les autres opérateurs relationnels sont implémentés en fonction de operator < .

inline bool operator< (const X& lhs, const X& rhs) { /* effectuer la comparaison réelle */ }
inline bool operator> (const X& lhs, const X& rhs) { return rhs < lhs; }
inline bool operator<=(const X& lhs, const X& rhs) { return !(lhs > rhs); }
inline bool operator>=(const X& lhs, const X& rhs) { return !(lhs < rhs); }

De même, l'opérateur d'inégalité est généralement implémenté en fonction de operator == :

inline bool operator==(const X& lhs, const X& rhs) { /* effectuer la comparaison réelle */ }
inline bool operator!=(const X& lhs, const X& rhs) { return !(lhs == rhs); }

Lorsqu'une comparaison à trois voies (telle que std::memcmp ou std::string::compare ) est fournie, les six opérateurs de comparaison binaire peuvent être exprimés à travers celle-ci :

inline bool operator==(const X& lhs, const X& rhs) { return cmp(lhs,rhs) == 0; }
inline bool operator!=(const X& lhs, const X& rhs) { return cmp(lhs,rhs) != 0; }
inline bool operator< (const X& lhs, const X& rhs) { return cmp(lhs,rhs) <  0; }
inline bool operator> (const X& lhs, const X& rhs) { return cmp(lhs,rhs) >  0; }
inline bool operator<=(const X& lhs, const X& rhs) { return cmp(lhs,rhs) <= 0; }
inline bool operator>=(const X& lhs, const X& rhs) { return cmp(lhs,rhs) >= 0; }

Opérateur d'indice de tableau

Les classes définies par l'utilisateur qui fournissent un accès de type tableau permettant à la fois la lecture et l'écriture définissent généralement deux surcharges pour operator [ ] : des variantes const et non-const :

struct T
{
          value_t& operator[](std::size_t idx)       { return mVector[idx]; }
    const value_t& operator[](std::size_t idx) const { return mVector[idx]; }
};

Alternativement, ils peuvent être exprimés comme une fonction membre template unique en utilisant un paramètre objet explicite :

struct T
{
    decltype(auto) operator[](this auto& self, std::size_t idx) 
    { 
        return self.mVector[idx]; 
    }
};
(depuis C++23)

Si le type de valeur est connu comme étant un type scalaire, la variante const doit retourner par valeur.

Lorsque l'accès direct aux éléments du conteneur n'est pas souhaité ou possible, ou pour distinguer l'utilisation de lvalue c [ i ] = v ; et de rvalue v = c [ i ] ; , operator [ ] peut renvoyer un proxy. Voir par exemple std::bitset::operator[] .

operator [ ] ne peut prendre qu'un seul indice. Afin de fournir une sémantique d'accès aux tableaux multidimensionnels, par exemple pour implémenter un accès à un tableau 3D a [ i ] [ j ] [ k ] = x ; , operator [ ] doit renvoyer une référence à un plan 2D, qui doit avoir son propre operator [ ] qui renvoie une référence à une ligne 1D, qui doit avoir operator [ ] qui renvoie une référence à l'élément. Pour éviter cette complexité, certaines bibliothèques optent pour la surcharge de operator ( ) à la place, de sorte que les expressions d'accès 3D aient la syntaxe de type Fortran a ( i, j, k ) = x ; .

(jusqu'en C++23)

operator [ ] peut prendre n'importe quel nombre d'indices. Par exemple, un operator [ ] d'une classe de tableau 3D déclarée comme T & operator [ ] ( std:: size_t x, std:: size_t y, std:: size_t z ) ; peut accéder directement aux éléments.

#include <array>
#include <cassert>
#include <iostream>
template<typename T, std::size_t Z, std::size_t Y, std::size_t X>
struct Array3d
{
    std::array<T, X * Y * Z> m{};
    constexpr T& operator[](std::size_t z, std::size_t y, std::size_t x) // C++23
    {
        assert(x < X and y < Y and z < Z);
        return m[z * Y * X + y * X + x];
    }
};
int main()
{
    Array3d<int, 4, 3, 2> v;
    v[3, 2, 1] = 42;
    std::cout << "v[3, 2, 1] = " << v[3, 2, 1] << '\n';
}

Sortie :

v[3, 2, 1] = 42
(depuis C++23)

Opérateurs arithmétiques bit à bit

Les classes et énumérations définies par l'utilisateur qui implémentent les exigences de BitmaskType doivent surcharger les opérateurs arithmétiques bit à bit operator & , operator | , operator ^ , operator~ , operator & = , operator | = , et operator ^ = , et peuvent optionnellement surcharger les opérateurs de décalage operator << operator >> , operator >>= , et operator <<= . Les implémentations canoniques suivent généralement le modèle décrit ci-dessus pour les opérateurs arithmétiques binaires.

Opérateur de négation booléenne

L'opérateur operator ! est couramment surchargé par les classes définies par l'utilisateur destinées à être utilisées dans des contextes booléens. Ces classes fournissent également une fonction de conversion définie par l'utilisateur vers le type booléen (voir std::basic_ios pour l'exemple de la bibliothèque standard), et le comportement attendu de operator ! est de renvoyer la valeur opposée de operator bool .

(jusqu'à C++11)

Étant donné que l'opérateur intégré ! effectue une conversion contextuelle en bool , les classes définies par l'utilisateur destinées à être utilisées dans des contextes booléens peuvent uniquement fournir operator bool et n'ont pas besoin de surcharger operator ! .

(depuis C++11)

Opérateurs rarement surchargés

Les opérateurs suivants sont rarement surchargés :

  • L'opérateur d'adresse, operator & . Si l'opérateur unaire & est appliqué à une lvalue de type incomplet et que le type complet déclare un operator & surchargé, il n'est pas spécifié si l'opérateur a la signification intégrée ou si la fonction opérateur est appelée. Comme cet opérateur peut être surchargé, les bibliothèques génériques utilisent std::addressof pour obtenir les adresses des objets de types définis par l'utilisateur. L'exemple le plus connu d'un operator & surchargé canonique est la classe Microsoft CComPtrBase . Un exemple d'utilisation de cet opérateur dans un EDSL peut être trouvé dans boost.spirit .
  • Les opérateurs logiques booléens, operator && et operator || . Contrairement aux versions intégrées, les surcharges ne peuvent pas implémenter l'évaluation en court-circuit. Également contrairement aux versions intégrées, elles ne séquencent pas leur opérande gauche avant l'opérande droit. (jusqu'à C++17) Dans la bibliothèque standard, ces opérateurs ne sont surchargés que pour std::valarray .
  • L'opérateur virgule, operator, . Contrairement à la version intégrée, les surcharges ne séquencent pas leur opérande gauche avant l'opérande droit. (jusqu'à C++17) Comme cet opérateur peut être surchargé, les bibliothèques génériques utilisent des expressions telles que a, void ( ) , b au lieu de a, b pour séquencer l'exécution d'expressions de types définis par l'utilisateur. La bibliothèque boost utilise operator, dans boost.assign , boost.spirit , et d'autres bibliothèques. La bibliothèque d'accès aux bases de données SOCI surcharge également operator, .
  • L'opérateur d'accès membre via pointeur sur membre operator - > * . Il n'y a pas d'inconvénients spécifiques à la surcharge de cet opérateur, mais il est rarement utilisé en pratique. Il a été suggéré qu'il pourrait faire partie d'une interface de pointeur intelligent , et est en effet utilisé dans cette capacité par les acteurs dans boost.phoenix . Il est plus courant dans les EDSL tels que cpp.react .

Notes

Macro de test de fonctionnalité Valeur Std Fonctionnalité
__cpp_static_call_operator 202207L (C++23) static operator ( )
__cpp_multidimensional_subscript 202211L (C++23) static operator [ ]

Mots-clés

operator

Exemple

#include <iostream>
class Fraction
{
    // ou std::gcd de C++17
    constexpr int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); }
    int n, d;
public:
    constexpr Fraction(int n, int d = 1) : n(n / gcd(n, d)), d(d / gcd(n, d)) {}
    constexpr int num() const { return n; }
    constexpr int den() const { return d; }
    constexpr Fraction& operator*=(const Fraction& rhs)
    {
        int new_n = n * rhs.n / gcd(n * rhs.n, d * rhs.d);
        d = d * rhs.d / gcd(n * rhs.n, d * rhs.d);
        n = new_n;
        return *this;
    }
};
std::ostream& operator<<(std::ostream& out, const Fraction& f)
{
   return out << f.num() << '/' << f.den();
}
constexpr bool operator==(const Fraction& lhs, const Fraction& rhs)
{
    return lhs.num() == rhs.num() && lhs.den() == rhs.den();
}
constexpr bool operator!=(const Fraction& lhs, const Fraction& rhs)
{
    return !(lhs == rhs);
}
constexpr Fraction operator*(Fraction lhs, const Fraction& rhs)
{
    return lhs *= rhs;
}
int main()
{
    constexpr Fraction f1{3, 8}, f2{1, 2}, f3{10, 2};
    std::cout << f1 << " * " << f2 << " = " << f1 * f2 << '\n'
              << f2 << " * " << f3 << " = " << f2 * f3 << '\n'
              <<  2 << " * " << f1 << " = " <<  2 * f1 << '\n';
    static_assert(f3 == f2 * 10);
}

Sortie :

3/8 * 1/2 = 3/16
1/2 * 5/1 = 5/2
2 * 3/8 = 3/4

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Appliqué à Comportement publié Comportement corrigé
CWG 1481 C++98 l'opérateur de pré-incrément non-membre ne pouvait avoir qu'un paramètre
de type classe, type énumération, ou un type référence vers ces types
aucune exigence de type
CWG 2931 C++23 les fonctions opérateur membres à objet explicite ne pouvaient avoir aucun paramètre
de type classe, type énumération, ou un type référence vers ces types
interdit

Voir aussi

Opérateurs courants
affectation incrémentation
décrémentation
arithmétique logique comparaison accès
membre
autres

a = b
a + = b
a - = b
a * = b
a / = b
a % = b
a & = b
a | = b
a ^ = b
a <<= b
a >>= b

++ a
-- a
a ++
a --

+ a
- a
a + b
a - b
a * b
a / b
a % b
~a
a & b
a | b
a ^ b
a << b
a >> b

! a
a && b
a || b

a == b
a ! = b
a < b
a > b
a <= b
a >= b
a <=> b

a [ ... ]
* a
& a
a - > b
a. b
a - > * b
a. * b

appel de fonction

a ( ... )
virgule

a, b
conditionnel

a ? b : c
Opérateurs spéciaux

static_cast convertit un type en un autre type apparenté
dynamic_cast convertit au sein des hiérarchies d'héritage
const_cast ajoute ou supprime les cv -qualificateurs
reinterpret_cast convertit un type en un type non apparenté
Cast de style C convertit un type en un autre par un mélange de static_cast , const_cast , et reinterpret_cast
new crée des objets avec une durée de stockage dynamique
delete détruit les objets précédemment créés par l'expression new et libère la zone mémoire obtenue
sizeof interroge la taille d'un type
sizeof... interroge la taille d'un pack (depuis C++11)
typeid interroge les informations de type d'un type
noexcept vérifie si une expression peut lever une exception (depuis C++11)
alignof interroge les exigences d'alignement d'un type (depuis C++11)

Liens externes

  1. Surcharge d'opérateur sur StackOverflow FAQ C++