2012-05-04 8 views
5

Si uso auto_ptr como valor de retorno de una función que rellena vectores grandes, esto hace que la función sea una función fuente (creará un auto_ptr interno y pasará la propiedad cuando devuelve un no const auto_ptr). Sin embargo, no puedo usar esta función con algoritmos STL porque, para acceder a los datos, necesito desrefigurar el auto_ptr. Un buen ejemplo supongo que sería un campo de vectores de tamaño N, con cada vector con 100 componentes. Si la función devuelve cada vector componente 100 por valor o por ref no es lo mismo, si N es grande.optimización del valor de retorno vs auto_ptr para vectores grandes

Además, cuando intento este código muy básico:

class t 
{ 
    public: 
     t() { std::cout << "ctor" << std::endl; } 
     ~t() { std::cout << "dtor" << std::endl; } 
}; 

t valueFun() 
{ 
    return t(); 
} 

std::auto_ptr<t> autoFun() 
{ 
    return std::auto_ptr(new t()); 
} 

tanto autoFun y llamadas divertidas resultado con la salida

Ctor Dtor

por lo que no puede ver realmente la variable automática que se está creando para pasar a la declaración de devolución. ¿Esto significa que la optimización del valor de retorno está configurada para la llamada valueFun? ¿ValueFun crea dos objetos automáticos en este caso?

¿Cómo puedo optimizar una población de una estructura de datos tan grande con una función?

+0

¿Está preguntando si RVO también funcionará para sus vectores grandes? Si es así, ¿no puedes probarlo con un ejemplo como el de arriba? – juanchopanza

+0

Cuando lo pruebo, ¿significa que funciona para todos los compiladores/plataformas? ¿Cómo sé que RVO está incluido en absoluto, debería leer las especificaciones del compilador? ¿Qué sucede si el código se compila en un clúster HPC con un compilador diferente y la biblioteca es grande? – tmaric

+0

Sí, entiendo tu punto. Es una de esas cosas que el compilador puede, pero no es obligatorio, así que nunca puede estar seguro. Por cierto, ¿tienes soporte para C++ 11? – juanchopanza

Respuesta

4

hay muchos opciones para esto, y la asignación dinámica puede no ser la mejor.


Antes de profundizar en esta discusión: ¿se trata de un cuello de botella?

Si no perfiló y se aseguró de que se tratara de un cuello de botella, esta discusión podría ser completamente inaceptable ... Recuerde que crear perfiles de depuración es bastante inútil.


Ahora, en C++ 03 hay varias opciones, desde la más agradable al paladar a lo mínimo:

  • confianza del compilador: las variables identificadas utilizan RVO incluso en versiones de depuración en gcc, por ejemplo.
  • utilizan un parámetro "out" (el paso por referencia)
  • asignan en el montón y devolver un puntero (inteligente o no)
  • verificación de la salida del compilador

Personalmente, me gustaría confiar en mi compilador en esto a menos que un perfilador demuestre que estoy equivocado.

En C++ 11, la semántica de movimiento nos ayuda a tener más confianza, porque siempre que haya una declaración return, si RVO no puede activarse, entonces un constructor de movimiento (si está disponible) se puede usar automáticamente; y mover constructores en vector son muy baratos.

Por lo tanto, se convierte en:

  • confianza del compilador: o bien RVO o mover la semántica
  • asignan en el montón y devuelven un unique_ptr

pero en realidad el segundo punto se debe utilizar sólo para esas pocas clases donde la semántica de movimiento no ayuda mucho: el costo de la semántica de movimiento suele ser proporcional al retorno de sizeof, por ejemplo, un std::array<T,10> tiene un tamaño igual a 10*sizeof(T) por lo que no es t tan bueno y podría beneficiarse de la asignación de montón + unique_ptr.


Tangente: confía en su compilador ya. Confías en que te advierte sobre errores, confías en que te advierte sobre construcciones peligrosas/probablemente incorrectas, confías en que traduzca correctamente tu código al ensamblaje de la máquina, confías en aplicar una optimización significativa para obtener una aceleración decente. No confiar en que un compilador aplique RVO en casos obvios es como no confiarle a su cardiólogo un billete de $ 10: es la menor de sus preocupaciones. ;)

+1

¡Muchas gracias por la tangente! :) – tmaric

1

Estoy bastante seguro de que el compilador realizará la optimización del valor de retorno para valueFun. Los principales casos en los que la optimización del valor de retorno no puede ser aplicada por el compilador son:

  • parámetros que regresan
  • devolviendo un objeto diferente basado en un condicional

Así, el auto_ptr no es necesario, y sería incluso más lento debido a tener que usar el montón.

Si todavía le preocupan los costos de desplazarse por un vector tan grande, puede utilizar la semántica de movimiento (std::vector aCopy(std::move(otherVector)) de C++ 11). Son casi tan rápidos como RVO y se pueden usar en cualquier lugar (que también se garantiza que se utilizará para los valores de retorno cuando RVO no es capaz de ser utilizado.)

creo compiladores más modernos semántica apoyo mover (o referencias rvalue técnicamente) en este punto

+0

El "bastante seguro" es lo que me molesta un poco. :) Desde mi punto de vista, si voy a ejecutar esto en cientos de núcleos y si crecerá con el tiempo, necesito estar 100% seguro de lo que hace el código. – tmaric

Cuestiones relacionadas