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

Los operadores de asignación modifican el valor del objeto.

Nombre del operador Sintaxis Sobrecargable Ejemplos de prototipo (para class T )
Dentro de la definición de clase Fuera de la definición de clase
asignación simple a = b T & T :: operator = ( const T2 & b ) ; N/A
asignación de adición a += b T & T :: operator + = ( const T2 & b ) ; T & operator + = ( T & a, const T2 & b ) ;
asignación de resta a -= b T & T :: operator - = ( const T2 & b ) ; T & operator - = ( T & a, const T2 & b ) ;
asignación de multiplicación a *= b T & T :: operator * = ( const T2 & b ) ; T & operator * = ( T & a, const T2 & b ) ;
asignación de división a /= b T & T :: operator / = ( const T2 & b ) ; T & operator / = ( T & a, const T2 & b ) ;
asignación de resto a %= b T & T :: operator % = ( const T2 & b ) ; T & operator % = ( T & a, const T2 & b ) ;
asignación AND bit a bit a &= b T & T :: operator & = ( const T2 & b ) ; T & operator & = ( T & a, const T2 & b ) ;
Asignación OR bit a bit a |= b T & T :: operator | = ( const T2 & b ) ; T & operator | = ( T & a, const T2 & b ) ;
asignación XOR bit a bit a ^= b T & T :: operator ^ = ( const T2 & b ) ; T & operator ^ = ( T & a, const T2 & b ) ;
asignación de desplazamiento a la izquierda bit a bit a <<= b T & T :: operator <<= ( const T2 & b ) ; T & operator <<= ( T & a, const T2 & b ) ;
asignación de desplazamiento a la derecha bit a bit a >>= b T & T :: operator >>= ( const T2 & b ) ; T & operator >>= ( T & a, const T2 & b ) ;
Notas
  • Todos los operadores de asignación integrados devuelven * this , y la mayoría de las sobrecargas definidas por el usuario también devuelven * this para que los operadores definidos por el usuario puedan usarse de la misma manera que los integrados. Sin embargo, en una sobrecarga de operador definida por el usuario, se puede utilizar cualquier tipo como tipo de retorno (incluyendo void ).
  • T2 puede ser cualquier tipo incluyendo T .

Contenidos

Definiciones

Asignación de copia reemplaza los contenidos del objeto a con una copia de los contenidos de b ( b no se modifica). Para tipos de clase, esto se realiza en una función miembro especial, descrita en el operador de asignación de copia .

Asignación de movimiento reemplaza el contenido del objeto a con el contenido de b , evitando la copia si es posible ( b puede ser modificado). Para tipos de clase, esto se realiza en una función miembro especial, descrita en el operador de asignación de movimiento .

(desde C++11)

Para tipos no clase, la asignación por copia y la asignación por movimiento son indistinguibles y se denominan asignación directa .

Asignación compuesta reemplaza el contenido del objeto a con el resultado de una operación binaria entre el valor anterior de a y el valor de b .

Sintaxis del operador de asignación

Las expresiones de asignación tienen la forma

target-expr = new-value (1)
target-expr op new-value (2)
target-expr - la expresión [1] que será asignada
op - uno de * = , / = % = , + = - = , <<= , >>= , & = , ^ = , | =
new-value - la expresión [2] (hasta C++11) cláusula de inicialización (desde C++11) a asignar al objetivo
  1. target-expr debe tener mayor precedencia que una expresión de asignación.
  2. new-value no puede ser una expresión de coma, porque su precedencia es menor.
1) Expresión de asignación simple.
2) Expresión de asignación compuesta.

Si new-value no es una expresión, la expresión de asignación nunca coincidirá con un operador de asignación compuesta sobrecargado.

(since C++11)

Operador de asignación simple incorporado

Para la asignación simple incorporada, target-expr debe ser un lvalue modificable.

El objeto referenciado por target-expr es modificado reemplazando su valor con el resultado de new-value . Si el objeto referenciado es de un tipo entero T , y el resultado de new-value es del tipo entero con signo/sin signo correspondiente, el valor del objeto es reemplazado con el valor de tipo T con la misma representación de valor del resultado de new-value .

El resultado de una asignación simple incorporada es un lvalue del tipo de target-expr , que hace referencia a target-expr . Si target-expr es un campo de bits , el resultado también es un campo de bits.

Asignación desde una expresión

Si new-value es una expresión, se convierte implícitamente al tipo sin calificadores cv de target-expr . Cuando target-expr es un campo de bits que no puede representar el valor de la expresión, el valor resultante del campo de bits está definido por la implementación.

Si target-expr y new-value identifican objetos que se superponen, el comportamiento es indefinido (a menos que la superposición sea exacta y el tipo sea el mismo).

Si el tipo de target-expr está calificado como volatile, la asignación está obsoleta, a menos que la expresión de asignación (posiblemente entre paréntesis) sea una expresión de valor descartado o un operando no evaluado .

(since C++20)


Asignación desde una cláusula inicializadora no expresión

new-value solo se permite que no sea una expresión en las siguientes situaciones:

  • target-expr es de tipo escalar T , y new-value está vacío o tiene solo un elemento. En este caso, dada una variable inventada t declarada e inicializada como T t = new-value  , el significado de x = new-value  es x = t .
  • target-expr es de tipo clase. En este caso, new-value se pasa como argumento a la función de operador de asignación seleccionada por resolución de sobrecarga .
#include <complex>
std::complex<double> z;
z = {1, 2};  // meaning z.operator=({1, 2})
z += {1, 2}; // meaning z.operator+=({1, 2})
int a, b;
a = b = {1}; // meaning a = b = 1;
a = {1} = b; // syntax error
(desde C++11)

En la resolución de sobrecarga frente a operadores definidos por el usuario , para cada tipo T , las siguientes firmas de función participan en la resolución de sobrecarga:

T * & operador = ( T * & , T * ) ;
T * volatile & operador = ( T * volatile & , T * ) ;

Para cada tipo de enumeración o puntero a miembro T , opcionalmente calificado con volatile, la siguiente firma de función participa en la resolución de sobrecarga:

T & operator = ( T & , T ) ;

Para cada par A1 y A2 , donde A1 es un tipo aritmético (opcionalmente calificado como volatile) y A2 es un tipo aritmético promovido, la siguiente firma de función participa en la resolución de sobrecarga:

A1 & operator = ( A1 & , A2 ) ;

Operador de asignación compuesta incorporado

El comportamiento de cada expresión de asignación compuesta incorporada target-expr op  = new-value es exactamente igual al comportamiento de la expresión target-expr = target-expr op new-value , excepto que target-expr se evalúa solo una vez.

Los requisitos sobre target-expr y new-value de los operadores de asignación simples incorporados también se aplican. Además:

  • Para + = y - = , el tipo de target-expr debe ser un tipo aritmético o un puntero a un tipo objeto completamente definido (posiblemente calificado cv).
  • Para todos los demás operadores de asignación compuesta, el tipo de target-expr debe ser un tipo aritmético.

En la resolución de sobrecarga frente a operadores definidos por el usuario , para cada par A1 y A2 , donde A1 es un tipo aritmético (opcionalmente calificado como volatile) y A2 es un tipo aritmético promovido, las siguientes firmas de función participan en la resolución de sobrecarga:

A1 & operador * = ( A1 & , A2 ) ;
A1 & operador / = ( A1 & , A2 ) ;
A1 & operador + = ( A1 & , A2 ) ;
A1 & operador - = ( A1 & , A2 ) ;

Para cada par I1 y I2 , donde I1 es un tipo integral (opcionalmente calificado como volatile) y I2 es un tipo integral promovido, las siguientes firmas de función participan en la resolución de sobrecarga:

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

Para cada tipo de objeto opcionalmente calificado cv T , las siguientes firmas de función participan en la resolución de sobrecarga:

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 ) ;

Ejemplo

#include <iostream>
int main()
{
    int n = 0;        // no es una asignación
    n = 1;            // asignación directa
    std::cout << n << ' ';
    n = {};           // inicialización a cero, luego asignación
    std::cout << n << ' ';
    n = 'a';          // promoción entera, luego asignación
    std::cout << n << ' ';
    n = {'b'};        // conversión explícita, luego asignación
    std::cout << n << ' ';
    n = 1.0;          // conversión de punto flotante, luego asignación
    std::cout << n << ' ';
//  n = {1.0};        // error del compilador (conversión restrictiva)
    int& r = n;       // no es una asignación
    r = 2;            // asignación a través de referencia
    std::cout << n << ' ';
    int* p;
    p = &n;           // asignación directa
    p = nullptr;      // conversión a puntero nulo, luego asignación
    std::cout << p << ' ';
    struct { int a; std::string s; } obj;
    obj = {1, "abc"}; // asignación desde una lista de inicialización entre llaves
    std::cout << obj.a << ':' << obj.s << '\n';
}

Salida posible:

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

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.

DR Se aplica a Comportamiento publicado Comportamiento correcto
CWG 1527 C++11 para asignaciones a objetos de tipo clase, el operando derecho
solo podía ser una lista de inicialización cuando la asignación
estaba definida por un operador de asignación definido por el usuario
se eliminó la restricción de asignación
definida por el usuario
CWG 1538 C++11 E1 = { E2 } era equivalente a E1 = T ( E2 )
( T es el tipo de E1 ), esto introducía un cast estilo C
es equivalente
a E1 = T { E2 }
CWG 2654 C++20 los operadores de asignación compuesta para tipos
calificados con volatile se depreciaban de forma inconsistente
ninguno de ellos
está depreciado
CWG 2768 C++11 una asignación desde una cláusula inicializadora no-expresión
a un valor escalar realizaría inicialización de lista directa
realiza inicialización de lista
por copia en su lugar
CWG 2901 C++98 el valor asignado a un objeto unsigned int
a través de un lvalue int no estaba claro
se aclaró
P2327R1 C++20 los operadores de asignación compuesta bit a bit para tipos volatile
se depreciaban siendo útiles para algunas plataformas
no están
depreciados

Véase también

Precedencia de operadores

Sobrecarga de operadores

Operadores comunes
asignación incremento
decremento
aritméticos lógicos comparación acceso a
miembros
otros

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

llamada a función

a ( ... )
coma

a, b
condicional

a ? b : c
Operadores especiales

static_cast convierte un tipo a otro tipo relacionado
dynamic_cast convierte dentro de jerarquías de herencia
const_cast añade o elimina cv -calificadores
reinterpret_cast convierte un tipo a un tipo no relacionado
Conversión estilo C convierte un tipo a otro mediante una mezcla de static_cast , const_cast , y reinterpret_cast
new crea objetos con duración de almacenamiento dinámico
delete destruye objetos previamente creados por la expresión new y libera el área de memoria obtenida
sizeof consulta el tamaño de un tipo
sizeof... consulta el tamaño de un pack (desde C++11)
typeid consulta la información de tipo de un tipo
noexcept comprueba si una expresión puede lanzar una excepción (desde C++11)
alignof consulta los requisitos de alineación de un tipo (desde C++11)

Documentación de C para Operadores de asignación