2012-03-31 3 views
7

En este fragmento de código, ¿qué constructor se llama realmente?¿Qué constructor se invoca aquí?

Vector v = getVector(); 

vector tiene constructor de copia, constructor predeterminado y operador de asignación:

class Vector { 
public: 
    ... 
    Vector(); 
    Vector(const Vector& other); 
    Vector& operator=(const Vector& other); 
}; 

getVector rendimientos por valor.

Vector getVector(); 

El código utiliza el estándar C++ 03.

Fragmento de código parece que se debe llamar al constructor predeterminado y luego al operador de asignación, pero sospecho que esta declaración es otra forma de usar el constructor de copia. ¿Cual es correcta?

Respuesta

8

Cuando aparece = en una inicialización, llama al constructor de copia. La forma general no es exactamente lo mismo que llamar directamente al constructor de copia. En la declaración T a = expr;, lo que sucede es que si expr es de tipo T, se llama al constructor de copia. Si expr no es de tipo T, primero se realiza una conversión implícita, si es posible, entonces se llama al constructor de copia con eso como argumento. Si una conversión implícita no es posible, entonces el código está mal formado.

Dependiendo de cómo getVector() se estructura, la copia puede ser optimizado de distancia, y el objeto que se ha creado dentro de la función es el mismo objeto físico que se almacena en el v.

+0

Una regla que no vale nada es que el constructor de copias debe ser accesible (por ejemplo, público) incluso si la construcción de copias termina siendo eliminada. Por lo tanto, puede hacer que el constructor de copias sea privado; el código no se compilará y, al hacerlo público, se compilará, pero no se llamará al constructor de copias. – 6502

+0

"el mismo objeto físico que se almacena en v", más bien, el objeto creado dentro de la función es el mismo objeto físico que 'v'. Normalmente diría que 'v' es el nombre de un objeto, o' v' es ese objeto, pero no "un objeto está almacenado en' v' ". La implementación habitual de esta elisión de copia es que la persona que llama de 'getVector' pasa un puntero como un parámetro oculto adicional, y' getVector' construye su valor de retorno en esa dirección. En este caso, el estándar permite que el código de llamada pase '& v' como ese parámetro oculto. –

0

El constructor de copia realidad se elide en este caso (marque this) y sólo el constructor por defecto termina siendo llamados

EDIT:

el constructor es sólo a veces elididas, según la respuesta de Benjamin. Por alguna razón, lo leí cuando llamas al constructor directamente.

2

Suponiendo que usted no ha hecho algo fuera patológica del código que está mostrando, su declaración es una copia de inicialización, y la segunda parte de esta regla se aplica:

13.3.1.3 Initialization by constructor [over.match.ctor] 

1 When objects of class type are direct-initialized (8.5), or copy-initialized from an 
    expression of the same or a derived class type (8.5), overload resolution selects the 
    constructor. For direct-initialization, the candidate functions are all the constructors 
    of the class of the object being initialized. For copy-initialization, the candidate 
    functions are all the converting constructors (12.3.1) of that class. The argument 
    list is the expression-list within the parentheses of the initializer. 

Para un caso simple prueba , ver post de Eli Bendersky, aquí: http://eli.thegreenplace.net/2003/07/23/variable-initialization-in-c/

1

siempre recuerde la regla:
Cada vez, se crea un objeto y se le dio un valor en la misma instrucción sola, entonces es Nunca una asignación.

Para añadir más,

Caso 1:

Vector v1; 
Vector v(v1); 

Caso 2:

Vector v = getVector(); 

En los dos formatos anteriores Caso 1 es inicialización directa mientras Caso 2 se conoce como Inicialización de copia.

¿Cómo funciona la inicialización de copia?
La inicialización de copia construye una secuencia de conversión implícita: Intenta convertir el valor devuelto de getVector() a un objeto de tipo Vector. A continuación, puede copiar el objeto creado en el objeto que se está inicializando, por lo que necesita un constructor de copia accesible.

Cuestiones relacionadas