Hasta hoy, siempre he pensado que los compiladores decentes convierten automáticamente struct pass-by-value en pass-by-reference si la estructura es lo suficientemente grande para que esta última sea más rápida. Según mi leal saber y entender, esto parece una optimización sin complicaciones. Sin embargo, para satisfacer mi curiosidad sobre si esto realmente sucede, creé un caso de prueba simple tanto en C++ como en D y miré la salida de GCC y Digital Mars D. Ambos insistieron en pasar estructuras de 32 bytes por valor cuando todo el La función en cuestión hizo fue sumar los miembros y devolver los valores, sin modificación de la estructura pasada. La versión de C++ está debajo.¿Por qué no pasar estructura por referencia una optimización común?
#include "iostream.h"
struct S {
int i, j, k, l, m, n, o, p;
};
int foo(S s) {
return s.i + s.j + s.k + s.l + s.m + s.n + s.o + s.p;
}
int main() {
S s;
int bar = foo(s);
cout << bar;
}
Mi pregunta es, ¿por qué diablos no sería algo como esto ser optimizado por el compilador para pasar por referencia en lugar de realmente empujar todos esos int
s en la pila?
Nota: Se utilizan los siguientes modificadores del compilador: GCC -O2 (-O3 inline foo().), DMD -O -inline-release.
Editar: Obviamente, en el caso general, la semántica de pass-by-value vs. pass-by-reference no será la misma, como si están involucrados constructores de copia o la estructura original está modificada en el callee . Sin embargo, en muchos escenarios del mundo real, la semántica será idéntica en términos de comportamiento observable. Estos son los casos sobre los que estoy preguntando.
Al realizar optimización de tiempo de enlace, a.k.a. generación de código de tiempo de enlace o compilación de programa completo, el compilador no necesita compilar la llamada solo en función de la declaración. Tiene una visión completa de lo que está pasando. Para compilar aplicaciones integradas que son sensibles al tamaño y velocidad, la generación de código de tiempo de enlace es la única manera de hacerlo. –