2009-10-05 11 views

Respuesta

17

Si son tipos de datos antiguos simples (POD), esto debería funcionar. Cualquier clase que tenga instancias de otras clases dentro de ella fallará potencialmente, ya que las está copiando sin invocar a sus constructores de copia. La forma más probable de que falle es que uno de sus destructores liberará algo de memoria, pero usted ha duplicado punteros que lo señalan, por lo que luego intenta usarlo desde uno de sus objetos copiados y obtener una segfault. En resumen, no lo hagas a menos que sea un POD y estés seguro de que siempre será un POD.

+0

Incluso POD es peligroso si un elemento es 'SomeType * x' y el espacio está asignado: ahora tiene dos copias de un puntero, y es probable que algo se borre por partida doble, lo cual no es bueno. –

+5

Arriesgado, sí, pero no es en sí mismo un error. Como el tipo es POD, no tiene un destructor furtivo que intentará eliminar el puntero, por lo que solo se borrará por partida doble si lo haces tú mismo. – jalf

10

No, hacerlo puede causar muchos problemas. Siempre debe copiar los tipos de C++ utilizando el operador de asignación o el constructor de copia.

El uso de una copia bit a bit interrumpe cualquier tipo de gestión de recursos porque al final del día se quedan 2 objetos para los cuales se ejecutó 1 constructor y se ejecutarán 2 destructores.

Considere como ejemplo un puntero ref contado.

void foo() { 
    RefPointer<int> p1(new int()); 
    RefPointer<int> p2; 
    memcpy(&p2,p1,sizeof(RefPointer<int>)); 
} 

Ahora ambos p1 y p2 están reteniendo los mismos datos sin embargo, el mecanismo de conteo ref interna no ha sido notificado. Ambos destructores se ejecutarán pensando que son el único propietario de los datos que potencialmente pueden causar la destrucción del valor dos veces.

+1

Vale la pena señalar que incluso con las clases POD'ish (es decir, campos POD solamente, pero, por ejemplo, también el método virtual), sigue siendo técnicamente U.B., incluso cuando funciona. –

0

Depende de la implementación del objeto C++ que está intentando copiar. En general, el propietario de la memoria del objeto C++ es el objeto en sí, por lo que tratar de "moverlo" o "copiarlo" con algo como memcopy_s va detrás de su espalda, lo que a menudo le ocasionará problemas.

Normalmente, si se pretende copiar o mover un objeto C++, existen API dentro de la misma clase que lo facilitan.

0

En general, si su estructura contiene punteros, no puede memcpy porque la estructura probablemente asigna espacios de memoria nuevos y los señala. Una memcpy no puede manejar eso.

Sin embargo, si su clase solo tiene tipos primitivos, no punteros, usted debería.

0

Además del problema de llamadas de administración de recursos desequilibradas en las dos instancias que termina después de una memcopy (como @JaredPar y @rmeador señaladas), si el objeto admite una noción de ID de instancia haciendo una memcopy se irá con dos instancias con la misma ID. Esto puede conducir a todo tipo de problemas "interesantes" para cazar más adelante, especialmente si sus objetos están mapeados en una base de datos.

1

Si es un objeto único, ¿por qué no usar el operador de asignación (supongo que el operador de asignación generado por el compilador podría implementarse en términos de memcpy si eso es tan ventajoso, y el compilador sabe mejor si su clase es un POD.)

Si desea copiar una matriz de objetos, puede usar std :: copy. Dependiendo de la implementación, esto puede terminar utilizando memmove (una cosa más que puede ensuciar, los almacenamientos intermedios pueden solaparse, no sé si el memcpy_s no estándar de alguna manera comprueba si los tipos implicados lo permiten). Nuevamente, la decisión es tomada por el compilador, que lo hará bien incluso si los tipos son modificados.