14

¿Es simplemente una preferencia o hay casos específicos donde uno es necesario sobre otro? Estoy refiriendo a las siguientes variantes para la inicialización¿Cuándo debe usar la inicialización directa y cuándo inicializar la copia?

T t(e); // direct initialization 
T t = e; // copy initialization 
+1

Qué es una asignación implícita? ¿Te refieres al operador de asignación predeterminado? – ybungalobill

+1

¿Qué quiere decir con "asignación implícita". –

+0

bool bValue1 = verdadero; // asignación explícita bool bValue2 (falso); // asignación implícita ¿Hace la diferencia? – Mike

Respuesta

19

Los nombres reales de las cosas que usted describe no es implícita y explícita, pero la asignación:

  • Copy-inicialización: T x = a;
  • Direct-inicialización : T x(a);

Ellos son no equivalente, más notablemente en contextos donde se requiere una conversión, por ejemplo, cuando T es del tipo de clase y a es de un tipo diferente (consulte el comentario Alf para ver ejemplos de contextos que ni siquiera implican la conversión). Consideremos el siguiente código:

class Test 
{ 
public: 
    explicit Test(int i) { /* ... */ } 
}; 

int main() 
{ 
    Test t(0); // OK : calls Test::Test(int) 
    Test u = 0; // KO : constructor is marked explicit 
} 

Parafraseando al estándar (8,5/14):

  • Para directo de inicialización y copia-inicialización donde el tipo de fuente es el mismo que, o una clase derivada de , la clase de destino, constructores se consideran
  • Para otros casos de copia de inicialización, como la segunda línea de main en mi ejemplo, secuencia de conversión definida por el usuario se consideran. Dado que el uso del constructor Test para la conversión implícita no fue permitido por la palabra clave explicit, la segunda línea no puede compilarse.
+0

"No son equivalentes en contextos en los que se requiere una conversión"; también hay otras situaciones en las que no son equivalentes. –

+0

@Alf: No estaba seguro de cuándo escribí esta oración, pero no pude encontrar ningún ejemplo. Podría estar equivocado con la terminología aquí, porque lo que veo en su respuesta * es * una conversión (a través de lo que el estándar llama un * converting constructor *), y en realidad es muy similar a mi respuesta (excepto por la parte de llaves que No he cubierto). Qué me estoy perdiendo ? – icecrime

+1

bueno, digamos 'a' es la expresión' T() '. :-) Entonces, la forma sintáctica de inicialización de copia es principalmente equivalente a la inicialización predeterminada (excepto que puede implicar un temporal y copia), mientras que la forma sintáctica de inicialización directa produce la interpretación como una declaración de función, el "análisis más irritante". Además, considere el caso de un constructor de copia 'explicit'. Y dependiendo de qué tan vagamente se le permita pensar aquí, considere el inicializador de llaves. Entonces, al menos 3 casos. Pero el contraejemplo directo es el constructor 'explicit'copy. Cheers, –

10

inicialización directa como

std::istringstream stream("blah blah"); 

es necesario cuando el tipo en cuestión, aquí std::istringstream de la biblioteca de C++ estándar, no tiene un constructor de copia accesible.

Una inicialización copia, como

std::istringstream stream = "blah blah"; //! NOT VALID 

requiere una constructor de copia accesible, porque se realiza como si se crea un objeto temporal en el lado derecho de =, y como si se utiliza ese temporal a continuación, para inicializar la variable que se está declarando

En la otra dirección, en C++ 98 se necesita la sintaxis de inicialización de copia para utilizar los inicializadores de llaves . Por ejemplo, la inicialización directa no se puede usar para inicializar un agregado. Pero puede utilizar la inicialización de copia con un inicializador de llaves:

#include <string> 
using namespace std; 

struct Answer 
{ 
    int  nVotes; 
    string description; 
};  

int main() 
{ 
    Answer const incorrect = { 26, "they're the same!" }; 
    Answer const correct  = { -1, "nah, they're different, actually" }; 
} 

Por lo tanto, hay diferencias significativas.

Generalmente prefiero la sintaxis de inicialización de copia debido a la claridad. Pero a veces, como se muestra arriba, la inicialización directa es, desafortunadamente, necesaria. Algunas personas, p.El autor de libros de texto de C++, Francis Glassborow, ha aterrizado en la inicialización directa como su sintaxis de inicialización preferida (no estoy seguro de por qué, es menos claro para mis ojos, y presenta el problema "más molesto"), y para ellos es la necesidad de copia la inicialización en algunos casos, eso es desafortunado.

Saludos & HTH.,

+1

Esta respuesta se escribió en 2010. Con C++ 11, la inicialización de copia * sintaxis * se puede usar en más casos, porque se reduce a la semántica de movimiento de C++ 11. Además, la sintaxis de inicialización directa se ha ampliado para incluir la lista de valores de llaves. –

Cuestiones relacionadas