Namespaces
Variants

Assignment operators

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

Les opérateurs d'assignation modifient la valeur de l'objet.

Nom de l'opérateur Syntaxe Surchargeable Exemples de prototypes (pour class T )
Définition à l'intérieur de la classe Définition à l'extérieur de la classe
Affectation simple a = b Oui T & T :: operator = ( const T2 & b ) ; N/A
Affectation par addition a += b Oui T & T :: operator + = ( const T2 & b ) ; T & operator + = ( T & a, const T2 & b ) ;
Affectation par soustraction a -= b Oui T & T :: operator - = ( const T2 & b ) ; T & operator - = ( T & a, const T2 & b ) ;
Affectation par multiplication a *= b Oui T & T :: operator * = ( const T2 & b ) ; T & operator * = ( T & a, const T2 & b ) ;
Affectation de division a /= b Oui T & T :: operator / = ( const T2 & b ) ; T & operator / = ( T & a, const T2 & b ) ;
Affectation du reste a %= b Oui T & T :: operator % = ( const T2 & b ) ; T & operator % = ( T & a, const T2 & b ) ;
Affectation ET bit à bit a &= b Oui T & T :: operator & = ( const T2 & b ) ; T & operator & = ( T & a, const T2 & b ) ;
Affectation par OU bit à bit a |= b Oui T & T :: operator | = ( const T2 & b ) ; T & operator | = ( T & a, const T2 & b ) ;
Affectation XOR bit à bit a ^= b Oui T & T :: operator ^ = ( const T2 & b ) ; T & operator ^ = ( T & a, const T2 & b ) ;
Affectation par décalage à gauche bit à bit a <<= b Oui T & T :: operator <<= ( const T2 & b ) ; T & operator <<= ( T & a, const T2 & b ) ;
affectation par décalage à droite au niveau du bit a >>= b Oui T & T :: operator >>= ( const T2 & b ) ; T & operator >>= ( T & a, const T2 & b ) ;
Notes
  • Tous les opérateurs d'affectation intégrés retournent * this , et la plupart des surcharges définies par l'utilisateur retournent également * this afin que les opérateurs définis par l'utilisateur puissent être utilisés de la même manière que les opérateurs intégrés. Cependant, dans une surcharge d'opérateur définie par l'utilisateur, n'importe quel type peut être utilisé comme type de retour (y compris void ).
  • T2 peut être n'importe quel type incluant T .

Table des matières

Définitions

Affectation par copie remplace le contenu de l'objet a par une copie du contenu de b ( b n'est pas modifié). Pour les types classe, cette opération est réalisée par une fonction membre spéciale, décrite dans l' opérateur d'affectation par copie .

Affectation par déplacement remplace le contenu de l'objet a par le contenu de b , en évitant la copie si possible ( b peut être modifié). Pour les types de classe, cela est effectué dans une fonction membre spéciale, décrite dans opérateur d'affectation par déplacement .

(depuis C++11)

Pour les types non-classes, l'assignation par copie et l'assignation par déplacement sont indiscernables et sont appelées assignation directe .

Affectation composée remplace le contenu de l'objet a par le résultat d'une opération binaire entre la valeur précédente de a et la valeur de b .

Syntaxe de l'opérateur d'affectation

Les expressions d'assignation ont la forme

target-expr = new-value (1)
target-expr op new-value (2)
**Note:** Le texte à traduire dans ce document HTML est principalement constitué de termes techniques C++ (`target-expr`, `new-value`, `op`) qui ne doivent pas être traduits selon les instructions. Les seuls éléments textuels sont les numéros de version (1) et (2) qui ne nécessitent pas de traduction. La structure HTML et les balises ont été préservées intactes.
target-expr - l'expression [1] à assigner
op - l'un des opérateurs * = , / = % = , + = - = , <<= , >>= , & = , ^ = , | =
new-value - la expression [2] (jusqu'à C++11) clause d'initialisation (depuis C++11) à assigner à la cible
  1. target-expr doit avoir une priorité supérieure à celle d'une expression d'affectation.
  2. new-value ne peut pas être une expression virgule, car sa priorité est inférieure.
1) Expression d'affectation simple.
2) Expression d'affectation composée.

Si new-value n'est pas une expression, l'expression d'affectation ne correspondra jamais à un opérateur d'affectation composé surchargé.

(depuis C++11)

Opérateur d'assignation simple intégré

Pour l'affectation simple intégrée, target-expr doit être une lvalue modifiable.

L'objet référencé par target-expr est modifié en remplaçant sa valeur par le résultat de new-value . Si l'objet référencé est d'un type entier T , et que le résultat de new-value est du type entier signé/non signé correspondant, la valeur de l'objet est remplacée par la valeur de type T ayant la même représentation de valeur que le résultat de new-value .

Le résultat d'une affectation simple intégrée est une lvalue du type de target-expr , se référant à target-expr . Si target-expr est un champ de bits , le résultat est également un champ de bits.

Affectation à partir d'une expression

Si new-value est une expression, elle est implicitement convertie vers le type non qualifié cv de target-expr . Lorsque target-expr est un champ de bits qui ne peut pas représenter la valeur de l'expression, la valeur résultante du champ de bits est définie par l'implémentation.

Si target-expr et new-value identifient des objets qui se chevauchent, le comportement est indéfini (sauf si le chevauchement est exact et que le type est identique).

Si le type de target-expr est qualifié volatile, l'affectation est dépréciée, sauf si l'expression d'affectation (éventuellement entre parenthèses) est une expression à valeur ignorée ou un opérande non évalué .

(depuis C++20)


Affectation à partir d'une clause d'initialisation non-expression

new-value n'est autorisé à ne pas être une expression que dans les situations suivantes :

  • target-expr est d'un type scalaire T , et new-value est vide ou ne contient qu'un seul élément. Dans ce cas, étant donné une variable inventée t déclarée et initialisée comme T t = new-value  , la signification de x = new-value  est x = t .
  • target-expr est d'un type classe. Dans ce cas, new-value est passé comme argument à la fonction d'opérateur d'affectation sélectionnée par résolution de surcharge .
#include <complex>
std::complex<double> z;
z = {1, 2};  // signification z.operator=({1, 2})
z += {1, 2}; // signification z.operator+=({1, 2})
int a, b;
a = b = {1}; // signification a = b = 1;
a = {1} = b; // erreur de syntaxe
(depuis C++11)

Dans la résolution de surcharge pour les opérateurs définis par l'utilisateur , pour chaque type T , les signatures de fonction suivantes participent à la résolution de surcharge :

T * & opérateur = ( T * & , T * ) ;
T * volatile & opérateur = ( T * volatile & , T * ) ;

Pour chaque type d'énumération ou pointeur sur membre T , optionnellement qualifié volatile, la signature de fonction suivante participe à la résolution de surcharge :

T & operator = ( T & , T ) ;

Pour chaque paire A1 et A2 , où A1 est un type arithmétique (éventuellement qualifié volatile) et A2 est un type arithmétique promu, la signature de fonction suivante participe à la résolution de surcharge :

A1 & operator = ( A1 & , A2 ) ;

Opérateur d'affectation composée intégré

Le comportement de chaque expression d'affectation composée intégrée target-expr op  = new-value est exactement le même que le comportement de l'expression target-expr = target-expr op new-value , sauf que target-expr n'est évalué qu'une seule fois.

Les exigences concernant target-expr et new-value des opérateurs d'affectation simples intégrés s'appliquent également. De plus :

  • Pour + = et - = , le type de target-expr doit être un type arithmétique ou un pointeur vers un type objet complètement défini (éventuellement qualifié cv).
  • Pour tous les autres opérateurs d'affectation composés, le type de target-expr doit être un type arithmétique.

Dans la résolution de surcharge pour les opérateurs définis par l'utilisateur , pour chaque paire A1 et A2 , où A1 est un type arithmétique (éventuellement qualifié volatile) et A2 est un type arithmétique promu, les signatures de fonction suivantes participent à la résolution de surcharge :

A1 & opérateur * = ( A1 & , A2 ) ;
A1 & opérateur / = ( A1 & , A2 ) ;
A1 & opérateur + = ( A1 & , A2 ) ;
A1 & opérateur - = ( A1 & , A2 ) ;

Pour chaque paire I1 et I2 , où I1 est un type intégral (éventuellement qualifié volatile) et I2 est un type intégral promu, les signatures de fonction suivantes participent à la résolution de surcharge :

I1 & operator % = ( I1 & , I2 ) ;
I1 & operator <<= ( I1 & , I2 ) ;
I1 & operator >>= ( I1 & , I2 ) ;
I1 & operator & = ( I1 & , I2 ) ;
I1 & operator ^ = ( I1 & , I2 ) ;
I1 & operator | = ( I1 & , I2 ) ;

Pour chaque type d'objet optionnellement qualifié cv T , les signatures de fonction suivantes participent à la résolution de surcharge :

T * & operator + = ( T * & , std:: ptrdiff_t ) ;
T * & operator - = ( T * & , std:: ptrdiff_t ) ;
T * volatile & operator + = ( T * volatile & , std:: ptrdiff_t ) ;
T * volatile & operator - = ( T * volatile & , std:: ptrdiff_t ) ;

Exemple

#include <iostream>
int main()
{
    int n = 0;        // pas une affectation
    n = 1;            // affectation directe
    std::cout << n << ' ';
    n = {};           // initialisation à zéro, puis affectation
    std::cout << n << ' ';
    n = 'a';          // promotion entière, puis affectation
    std::cout << n << ' ';
    n = {'b'};        // cast explicite, puis affectation
    std::cout << n << ' ';
    n = 1.0;          // conversion en virgule flottante, puis affectation
    std::cout << n << ' ';
//  n = {1.0};        // erreur de compilation (conversion restrictive)
    int& r = n;       // pas une affectation
    r = 2;            // affectation via référence
    std::cout << n << ' ';
    int* p;
    p = &n;           // affectation directe
    p = nullptr;      // conversion en pointeur nul, puis affectation
    std::cout << p << ' ';
    struct { int a; std::string s; } obj;
    obj = {1, "abc"}; // affectation depuis une liste d'initialisation entre accolades
    std::cout << obj.a << ':' << obj.s << '\n';
}

Sortie possible :

1 0 97 98 1 2 (nil) 1:abc

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 correct
CWG 1527 C++11 pour les affectations vers des objets de type classe, l'opérande droit
pouvait être une liste d'initialisation uniquement lorsque l'affectation
est définie par un opérateur d'affectation défini par l'utilisateur
supprimé la contrainte d'affectation
définie par l'utilisateur
CWG 1538 C++11 E1 = { E2 } était équivalent à E1 = T ( E2 )
( T est le type de E1 ), cela introduisait un cast de style C
c'est équivalent
à E1 = T { E2 }
CWG 2654 C++20 les opérateurs d'affectation composée pour les types
qualifiés volatile étaient dépréciés de manière incohérente
aucun d'eux
n'est déprécié
CWG 2768 C++11 une affectation depuis une clause d'initialisation non-expression
vers une valeur scalaire effectuerait une initialisation directe par liste
effectue une initialisation par liste
par copie à la place
CWG 2901 C++98 la valeur assignée à un objet unsigned int
via une lvalue int n'était pas claire
clarifié
P2327R1 C++20 les opérateurs d'affectation composée bit à bit pour les types volatile
étaient dépréciés alors qu'ils sont utiles pour certaines plateformes
ils ne sont pas
dépréciés

Voir aussi

Priorité des opérateurs

Surcharge d'opérateur

Opérateurs courants
assignation 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é
C-style cast 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)

Documentation C pour Opérateurs d'assignation