2010-08-08 15 views
58

Ich habe oft gelesen, dass die Durchsetzung von Const-Korrektheit in Ihrem C- oder C++ - Code nicht nur eine gute Praxis in Bezug auf Wartbarkeit ist, sondern es Ihrem Compiler auch erlauben kann, Optimierungen durchzuführen. Allerdings habe ich das komplette Gegenteil gelesen, auch —, dass es die Leistung überhaupt nicht beeinträchtigt.Kann Const-Korrektheit die Leistung verbessern?

Haben Sie Beispiele, in denen const Korrektheit Ihrem Compiler helfen könnte, die Leistung Ihres Programms zu verbessern?

+42

Const-Korrektheit ist eine der besten Praktiken in Bezug auf Wartbarkeit. Wenn Ihr C++ - Code nicht const-korrekt ist, ist es im Grunde genommen ein Haufen Mist, der darauf wartet, dass eine Katastrophe eintritt. Es ist nicht beabsichtigt, die Leistung zu beeinträchtigen. –

+1

@Neil Butterworth: leider ist das Gegenteil nicht wahr. – Beta

+3

Hier ist ein Beispiel, wo 'const' einen Leistungsunterschied gemacht hat: http://StackOverflow.com/questions/1121791/optimization-of-division-in-gcc. Es war jedoch im Wesentlichen ein Qualitätsproblem. 'const' hat nicht festgestellt, ob der Compiler * die Optimierung legal vornehmen kann, es ist einfach passiert, dass die Version des Compilers es nicht geschafft hat, wenn sie fehlte. –

Antwort

50

const Korrektheit kann die Leistung nicht verbessern, da const_cast und mutable in der Sprache sind, und Code entsprechend den Regeln zu brechen. Dies wird in C++ 11, wo Ihre const Daten z.B. sei ein Zeiger auf eine std::atomic, was bedeutet, dass der Compiler Änderungen von anderen Threads respektieren muss.

Es ist trivial für den Compiler, den Code zu sehen, den er generiert, und zu bestimmen, ob er tatsächlich in eine gegebene Variable schreibt, und Optimierungen entsprechend anzuwenden.

Das alles gesagt, const Korrektheit ist ein gut Sache in Bezug auf Wartbarkeit. Andernfalls könnten Clients Ihrer Klasse die internen Mitglieder dieser Klasse auflösen. Betrachten Sie zum Beispiel den Standard std::string::c_str() - wenn er keinen konstanten Wert zurückgeben könnte, wären Sie in der Lage, mit dem internen Puffer der Zeichenkette herumzulaufen!

Verwenden Sie aus Leistungsgründen nicht const. Verwenden Sie es aus Gründen der Wartungsfreundlichkeit.

+26

"du könntest mit dem internen Puffer der Schnur herumschrauben!" - Entscheidend wäre, dass Sie * versehentlich * mit dem internen Puffer umgehen können. Compiler-Fehler aufgrund von 'const' sind Wegweiser mit der Aussage:" Du machst etwas Dummes ". –

+1

@Steve: Guter Punkt. +1 zu kommentieren –

+4

... und Const-Casts sind Wegweiser, die sagen: "Der Autor dieses Codes versucht etwas cleveres zu tun" ;-) –

6

in meiner Erfahrung keine

Für Skalarvariablen, Compiler ist in der Lage, um zu bestimmen, wenn der Wert geändert wird, und führen Sie selbst notwendige Optimierung.

Bei Array-Zeigern ist die Korrektheit der Korrektheit keine Garantie dafür, dass Werte bei möglichen Alias-Problemen wirklich konstant sind. Daher Compiler kann nicht const Modifikator allein verwenden, um Optimierungen durchführen

wenn Sie Optimierung suchen, sollten Sie __restrict__ oder spezielle Funktion Modifikatoren betrachten/Attribute: http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

13

Ja kann es.

Die meisten const s sind rein zum Vorteil des Programmierers und nicht helfen, den Compiler zu optimieren, weil es legal ist, sie wegzuwerfen und so dem Compiler nichts Nützliches für die Optimierung zu sagen. Einige const s können jedoch nicht (legal) weggeworfen werden, und diese liefern dem Compiler nützliche Informationen zur Optimierung.

Als Beispiel kann der Zugriff auf eine globale Variable, die mit einem const Typ definiert wurde, inline ausgeführt werden, während eine ohne const Typ nicht inline sein kann, da sie sich zur Laufzeit ändern kann.

https://godbolt.org/g/UEX4NB

C++:

int foo1 = 1; 
const int foo2 = 2; 

int get_foo1() { 
    return foo1; 
} 

int get_foo2() { 
    return foo2; 
} 

asm:

foo1: 
     .long 1 
foo2: 
     .long 2 
get_foo1(): 
     push rbp 
     mov  rbp, rsp 
     mov  eax, DWORD PTR foo1[rip] ; foo1 must be accessed by address 
     pop  rbp 
     ret 
get_foo2(): 
     push rbp 
     mov  rbp, rsp 
     mov  eax, 2 ; foo2 has been replaced with an immediate 2 
     pop  rbp 
     ret 

in der Praxis, bedenken Sie, dass während const Leistung verbessern können, in den meisten Fällen wird es oder nicht wird aber die Änderung wird nicht auffallen. Die primäre Nützlichkeit von const ist keine Optimierung.

Steve Jessop gibt ein weiteres Beispiel in seinem Kommentar zu der ursprünglichen Frage, die etwas Erwähnenswertes bringt. In einem Blockbereich ist es möglich, dass ein Compiler ableitet, ob eine Variable mutiert ist, und entsprechend optimieren, unabhängig von const, da der Compiler alle Verwendungen der Variablen sehen kann. Im obigen Beispiel ist es hingegen unmöglich vorherzusagen, ob foo1 mutiert wird, da es in anderen Übersetzungseinheiten geändert werden könnte. Ich nehme an, ein hypothetischer Sentient-Ultra-Compiler könnte ein ganzes Programm analysieren und feststellen, ob es einen Inline-Zugriff auf foo1 gibt ... aber echte Compiler können das nicht.

Verwandte Themen