2009-04-14 14 views
10

¿Puedo escribir un constructor de copia simplemente pasando un puntero en lugar de la referencia de referencia? (¿Sería aceptable si me aseguro que yo no voy a cambiar cualquiera de los valores, aunque?)Copiar constructores - C++

así:

SampleClass::SampleClass(SampleClass* p) 
{ 
//do the necessary copy functionality 
} 

en lugar de:

SampleClass::SampleClass(const SampleClass& copyObj) 
{ 
//do the necessary copy 
} 

Gracias de antemano.


Gracias a todos. Entonces, si escribo un constructor que toma un puntero (y pensé que ese es mi constructor de copia), el compilador seguiría suministrando el constructor de copia predeterminado, en cuyo caso mi constructor (que yo creía era mi constructor de copia) no se llamaría y se llamaría al constructor de copia predeterminado. Lo tengo.

Respuesta

1

constructores Nº Copiar deben tener una referencia, no puntero, si se trata de ser útil para pasar por valor, etc.

4

Se puede escribir un constructor que toma un puntero como un argumento.
Pero el constructor de copia es el nombre que le damos a un constructor específico.
Un constructor que toma una referencia (preferiblemente const, pero no es obligatorio) de la misma clase que un argumento simplemente se llama el constructor de copia porque esto es lo que hace efectivamente.

19

Sí, puede escribir un constructor que tome un puntero al objeto. Sin embargo, no se puede llamar un constructor de copia. La misma definición de un constructor de copia requiere que pase un objeto de la misma clase. Si está pasando algo más, sí, es un constructor bien, pero no un constructor de copias.

1

Por definición, el copiador usa una referencia constante. Si bien no hay nada que te impida escribir un cursor que tome un puntero, plantea algunos problemas que no aparecen al usar una referencia, por ejemplo, ¿qué debería/podría suceder si se pasa un puntero nulo?

1

Un constructor de copia necesita una referencia debido a que un parámetro de valor requeriría hacer una copia, lo cual invocará el constructor de copia, lo que haría una copia de su parámetro, lo cual invocará el constructor de copia, que ...

1

Puede escribir un constructor así, pero no es técnicamente un constructor de copia. Por ejemplo, los contenedores STL seguirán utilizando el constructor de copia generado por el compilador (el compilador genera uno porque no escribió uno).

2

Además del hecho de que no sería un constructor de copia y el compilador generará el constructor de copia a menos que lo deshabilite explícitamente, no hay nada que ganar y mucho perder. ¿Cuál es la semántica correcta para un constructor con un puntero nulo? ¿Qué agrega esto al usuario de su clase? (Sugerencia: nada, si quiere construir a partir de un objeto de montón, puede desreferenciar el puntero y usar el constructor de copia normal).

1

El constructor de copia se utiliza implícitamente en dos casos:

  • Cuando una instancia de la clase se pasa por valor de una función.
  • Cuando se devuelve una instancia de su clase por valor desde una función.

Como han mencionado otros, puede escribir un constructor con la firma descrita (o con un puntero const), pero no se usará en ninguno de los casos anteriores.

-1

Puede escribir un constructor de copia perfectamente válido y aún así poder pasar una referencia que sea NULL. Puede probar NULL, pero solo si no utiliza listas de inicialización de constructor.

Ejemplo:

MyClass::MyClass(MyClass const& MyClassCopy) 
: somevar(MyClassCopy.somevar) // <- the init list goes here. 
{ 
    // If MyClassCopy is NULL, the initialization above is doomed! 
    // However we can check for NULL in the constructor body but 
    // the initialization list must be removed ... 
    if (&MyClassCopy == NULL) throw(std::runtime_error("NULL pointer!")); 
    somevar = MyClassCopy.somevar; 
} 

// I'll now do some very dangerous programming to 
// demonstrate one way that a NULL can get through ... 
MyClass* P = NULL; 
MyClass A(*P); // Bang, you're dead! 

Por lo que yo sé, no hay manera de comprobar si hay un NULL desde dentro de la lista de inicialización, por lo que si usted piensa que podría terminar con una situación en la que un valor NULL recibe a través de, tienes que probarlo en el cuerpo del constructor y hacer la inicialización desde allí.

No se olvide que hay un par de trampas con el operador :: = función() para estar al tanto de ...

+1

no se puede obtener una referencia nula sin invocar un comportamiento indefinido en dicho código. La prueba de NULL después del hecho no es útil, ya que el error está en el otro código. De hecho, el compilador puede optimizar la prueba 'if (& MyClassCopy == NULL)' porque nunca puede ocurrir en un programa correcto. –

+0

Acepto que quitar la referencia de un puntero NULL es una operación no válida, y la prueba para NULL se realiza mejor antes de la operación de eliminación de referencias. Sin embargo, debido a que el NULL se puede asignar durante el tiempo de ejecución, la mayoría de los compiladores le permitirán crear una referencia NULL y el compilador no podría verificarla. o para optimizar una prueba de salida NULL,. Puedes probarlo con g ++ y la prueba funciona. – Rob

+0

Después de un momento de reflexión, tiene razón, DEBE probar nulo antes de la operación de eliminación de referencia. La prueba después del hecho no está definida. – Rob