Pregunta

Recientemente escribí un fragmento de código que lo hizo

SomeClass someObject;
mysqlpp::StoreQueryResult result = someObject.getResult();

donde SomeClass :: getResult () se ve así:

mysqlpp::StoreQueryResult SomeClass::getResult()
{
mysqlpp::StoreQueryResult res = ...<something>...;
return res;
}

Ahora, usando el ejemplo en el primer fragmento de código, cuando compilé y ejecuté, el programa se bloqueó con una señal ABORTAR. Luego cambié el primer fragmento de código a:

SomeClass someObject;
mysqlpp::StoreQueryResult result(someObject.getResult());

que funcionó bien. Además, solo para probarlo, lo cambié nuevamente a:

SomeClass someObject;
mysqlpp::StoreQueryResult result;
result = someObject.getResult();

que también funcionó bien.

Ahora, no puedo entender por qué falló el primer ejemplo, y los dos siguientes tuvieron éxito. Según tengo entendido, en el primer ejemplo, el constructor de copia se usa para inicializar el resultado. ¿Pero no es este también el caso en el segundo ejemplo? Entonces, ¿por qué tuvo éxito el segundo ejemplo? El tercer ejemplo tiene un poco más de sentido: dado que la copia constante no se usa, solo asignamos después de la construcción.

En resumen, ¿cuál es la diferencia entre:

FooClass a = someObject.someMethodReturningFooClassInstance();

y

FooClass a(someObject.someMethodReturningFooClassInstance());?

¡Muchas gracias!

¿Fue útil?

Solución

No creo que haya ninguna diferencia en los dos casos. El mismo constructor de copia se llama las dos veces.

¿Estás seguro de que esto es exactamente lo que has escrito en tu código?

Otros consejos

Hablando estrictamente en el primer caso, se llama al constructor predeterminado seguido del operador de asignación y en el segundo caso usa solo el constructor de copia.

Bien, mi suposición inicial era errónea, y aparentemente en ambos casos solo se llamaría al constructor de copia (también en el caso de la asignación también se podría llamar a un constructor de conversión adicional). Arrancaré el compilador después de dormir un poco y verificaré esto en mi entorno de desarrollo.

Podrías poner un punto de interrupción (o incluso una declaración printf) dentro del constructor de la copia, y sabrías exactamente cuándo se llamó, ya sabes. SO no puede reemplazar la depuración básica. ;)

Pero sí, el constructor de copia debe llamarse en los dos primeros casos. El tercer caso utiliza el operador de asignación en su lugar.

¿Has intentado ejecutarlo en el depurador? Debería interrumpirse en una señal ABORT.

Bueno, en realidad, el primero hará una copia intermedia con operator =, mientras que el segundo hará una construcción de copia directa.

Creo que el primer caso es el valor asignado (valor correcto) al objeto. Es enviar valor al objeto. En el ejemplo 2,3 es Objeto implícito y concepto de objeto explícito. No debe escribir código por valor asignado al objeto directo.

En la teoría más pura, el constructor de copia debe llamarse en ambos casos. Sin embargo, hay algo que se llama Optimización del valor de retorno (RVO) que el compilador puede usar en estos casos. Si se utiliza RVO, no se llamará al constructor de la copia. Quizás su compilador usa RVO en un caso y no en el otro?

Editar: Esto solo se aplica al caso

SomeClass someObject;
mysqlpp::StoreQueryResult result;
result = someObject.getResult();
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top