Assignment operators
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 ) ; |
|
||||
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) | ||||||||
| 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 |
- ↑ target-expr doit avoir une priorité supérieure à celle d'une expression d'affectation.
- ↑ new-value ne peut pas être une expression virgule, car sa priorité est inférieure.
|
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-expressionnew-value n'est autorisé à ne pas être une expression que dans les situations suivantes :
#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
| Opérateurs courants | ||||||
|---|---|---|---|---|---|---|
| assignation |
incrémentation
décrémentation |
arithmétique | logique | comparaison |
accès
membre |
autres |
|
a
=
b
|
++
a
|
+
a
|
!
a
|
a
==
b
|
a
[
...
]
|
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é
|
||||||
|
Documentation C
pour
Opérateurs d'assignation
|