VS8 Compileroptimierung bei Methodenaufrufen
-
Hallo zusammen,
ich werde zu dem Problem gleich noch einen Test machen, aber sicherheitshalber geht die Frage an euch raus:
Optimiert der Compiler von VS8 Kopieroperationen, die keinen Sinn machen? Wenn ich eine Methode aufrufe und statt einer konstanten Referenz entgegenzunehmen eine Kopie erstelle, diese aber nicht angefasst wird, macht der Compiler daraus automatisch eine Referenz?
Gruß
-
Was meinst du mit Kopie erstellen? Kopie eines Übergabeparametes? Soweit ich weiß, wird daraus keine Referenz erstellt, wenn du das nicht explizit angibst. Die Kopie wird für die Lebenszeit der Funktion behalten und danach gelöscht. Zeige am besten Beispielcode.
-
Davon würde ich nicht ausgehen. Nur, wenn die Methode inline wird.
-
[Rewind] schrieb:
Was meinst du mit Kopie erstellen? Kopie eines Übergabeparametes?
Es ist ja erstmal egal, wann die Kopie erstellt wird, das kann bei einem Methodenaufruf sein also als Parameter oder auch bei Beendigung der Methode also als Rückgabewert.
Hier mein Beispiel, damit ist gezeigt, dass es so ist:
class Test { BigObject bigObject; public: const BigObject& GetObject() const { return bigObject; } };Test test; for (int i = 0; i < 100000; ++i) { BigObject bigObject = test.GetObject(); //bigObject.DoSomething(); <--- }Die Methode GetObject() gibt eine konstante Referenz zurück, im Code wird allerdings eine Kopie gespeichert. Je nach dem ob die markierte Zeile auskommentiert ist oder nicht, bricht das Programm mit einem StackOverflow ab. In Release kompiliert wird also bei Nichtbenutzung des Objekts automatisch eine Referenz erzeugt und somit auch kein neuer Speicher allokiert. Also habe ich Recht behalten

Ich bin zwar von mir aus drauf gekommen, aber falls es wen interessiert, hat der Thread ja doch noch seine Daseinsberechtigung.
Gruß
-
Kurzer Test mit VC9:
void test1(std::vector<int> v) { if(v.size()==1) cout << v[0] << '\n'; } void test2(const std::vector<int>& v) { if(v.size()==1) cout << v[0] << '\n'; }const int size = 10000000; std::vector<int> v(size); const int count = 100; for(int i=0;i<count;++i) test1(v);Das gleiche mit test2 und Zeitmessung:
1575 ms 0 ms
-
@Bonzy: Rückgabewert und Methodenaufruf sind zwei ganz verschiedene Probleme. Rückgaben können ganz leicht optimiert werden. Da sieht der aufrufende Code, dass er die Kopie nicht braucht und spart sie sich. Ruft der Code jedoch eine Funktion auf, so kann er in der Regel nicht sehen, was in der Funktion vor sich geht und muss die Kopie machen. Und die Funktion selber kann auch nicht einfach auf Referenz umschalten, sie muss sich an ihre eigene Schnittstelle halten, sonst geht der Aufruf schief.
Die einzige Möglichkeit dies zu optimieren ist also, wenn sowohl der aufrufende Code als auch der Code der Funkion gleichzeitig bekannt ist.
Dies ist die Ausnahme! Dafür gibt es recht neue Techniken, wie man das trotzdem optimieren kann. Bei Microsoft heißt das glaube ich "Link Time Optimization" und muss vermutlich explizit aktiviert werden, da es doch ganz schön Compilerressourcen verbraucht und auch ein paar andere Nachteile hat.
-
Ich habe gerade meinen Test umgeschrieben und bin nun zu dem Schluss gekommen, dass ich doch falsch lag. Mein Test war lediglich nicht richtig aufgesetzt, mit einem Gegenbeweis lässt sich einfach leichter hantieren.
