una que programacion orientada objetos objeto implementa ejemplos crear constructores construccion como codigo clases clase c++ c++14 language-lawyer c++17 explicit

que - programacion orientada a objetos c++ ejemplos



¿Qué cambios en C++ hicieron que la inicialización de la copia funcionara para una clase con un constructor explícito? (1)

Considere este código:

struct X{ explicit X(){} explicit X(const X&){} }; void foo(X a = X()){} int main(){}

Usando el estándar C ++ 14, tanto GCC 7.1 como el Clang 4.0 rejects el código, que es lo que esperaba.

Sin embargo, utilizando C ++ 17 ( -std=c++1z ), ambos aceptan el código. ¿Qué regla cambió?

Para que ambos compiladores exhiban este mismo comportamiento, dudo que esto sea un error. Pero por lo que puedo decir, el último borrador aún dice que el argumento predeterminado utiliza la semántica de la inicialización de la copia 1 . Una vez más, sabemos que los constructores explicit solo permitirán la inicialización directa 2 .

1 : dcl.fct.default/5 ; 2 : class.conv.ctor/2


Porque el comportamiento de la elección de copia cambia de C ++ 17; Para este caso la optimización es obligatoria.

En las siguientes circunstancias, los compiladores deben omitir los constructores de copia y movimiento de los objetos de clase, incluso si el constructor de copia / movimiento y el destructor tienen efectos secundarios observables:

  • En la inicialización, si la expresión de inicialización es un valor predefinido y la versión no calificada para el currículum vitae del tipo de origen es la misma clase que la clase de destino, la expresión de inicializador se usa para inicializar el objeto de destino:

    T x = T(T(T())); // only one call to default constructor of T, to initialize x

y para la inicialización de la copia :

Los efectos de la inicialización de la copia son:

  • Primero, si T es un tipo de clase y el inicializador es una expresión prvalue cuyo tipo cv no calificado es la misma clase que T , la propia expresión del inicializador, en lugar de un material materializado temporalmente, se usa para inicializar el objeto de destino: ver copia elision (desde C ++ 17)

  • Si T es un tipo de clase y la versión no calificada por CV del tipo de otro es T o una clase derivada de T , se examinan los constructores no explícitos de T y se selecciona la mejor coincidencia por resolución de sobrecarga. Luego se llama al constructor para inicializar el objeto.

Eso significa que para X a = X() , a se construirá por defecto directamente, los constructores de copiar / mover y sus efectos secundarios se omitirán completamente. La selección de constructores no explícitos para la resolución de sobrecarga no tendrá lugar, lo que se requiere en C ++ 14 (y antes). Para estos casos garantizados, los constructores de copiar / mover no participan, entonces no importa si son explicit o no.