const-correctnessはパフォーマンスを向上させることができますか?


92

CまたはC ++コードでconst-correctnessを適用することは、保守性に関して良い習慣であるだけでなく、コンパイラーが最適化を実行できるようになる可能性があることを何度も読みました。しかし、私も完全に反対のことを読みました—それはパフォーマンスにまったく影響を与えないということです。

したがって、constの正当性がコンパイラーのプログラムのパフォーマンス向上に役立つ可能性がある例はありますか?


50
定数の正確さは、保守性に関するベストプラクティスの1つです。C ++コードがconst-correctでない場合、それは基本的にはがらくたの山であり、災害が発生するのを待っています。パフォーマンスに影響を与えることを意図したものではありません。

2
@Neil Butterworth:残念ながら、その逆は当てはまりません。
ベータ版

6
constパフォーマンスに違いが生じた例を次に示します:stackoverflow.com/questions/1121791/…。ただし、これは本質的に実装の品質の問題でした。constコンパイラー合法的に最適化を行うことができるかどうかを判断しませんでした。コンパイラーのバージョンが欠落しているときに、それを行うことができなかっただけです。
Steve Jessop

3
「morgennebel」が最初の文の「のみ」を見逃したことは間違いありません。「これは良い習慣であるだけではありません」という方がはるかに理にかなっています。
ianH 2010

2
@IanHはい、私はそれを考慮しました。しかし、OPには明確にするための十分な時間がありました。質問を投稿した後、単に姿を消す人々に本当にうんざりします。

回答:


77

constconst_castmutableは言語であるため、正確さによってパフォーマンスを向上させることはできず、コードが規則に準拠して違反する可能性があります。これはC ++ 11ではさらに悪化します。constたとえば、データがへのポインタである可能性があるためstd::atomic、コンパイラは他のスレッドによって行われた変更を尊重する必要があります。

とは言うものの、コンパイラーが生成するコードを調べて、実際に特定の変数に書き込むかどうかを判断し、それに応じて最適化を適用するのは簡単です。

とはconstいえ、正しさは良いことです、保守性に関してことです。そうしないと、クラスのクライアントがそのクラスの内部メンバーを壊す可能性があります。たとえば、標準について考えてstd::string::c_str()みましょう。const値を返すことができなかった場合は、文字列の内部バッファをいじくり回すことができます。

constパフォーマンス上の理由から使用しないでください。保守性の理由で使用してください。


31
「文字列の内部バッファをいじくり回すことができるでしょう!」-決定的に、内部バッファを誤ってねじ込む可能性があります。によるコンパイラエラーconstは、「あなたは愚かなことをしている」という道標です。
Steve Jessop 2010

4
...そしてconst-castsは、「このコードの作者は何か賢いことをしようとしている」という道標です;-)
Steve Jessop 2010

5
@Steve Jessop-またはconst-castは、「constが正しいコードの束を、constが正しくないコードにボルトで固定しようとしていますが、どちらも修正できません」という標識です。これは、私に言わせれば、決して賢くはなく、ただ迷惑です。
Michael Kohne 2010

7
@ Michael-はい、フェアポイントです。おそらく、元の道標は「あなたは愚かなことをしている」ではなく、「誰かが愚かなことをしている」ということです。
Steve Jessop 2010

GodboltとArduinoは、constの正しさは楽しみのためだけではないと私に言いました。
dgrat 2017

31

はい、できます。

ほとんどconstのsは純粋にプログラマーの利益のためであり、それらをキャストすることは合法であり、コンパイラーに最適化に役立つことを何も伝えないため、コンパイラーの最適化には役立ちません。ただし、一部はconst(合法的に)キャストできず、これらはコンパイラーに最適化に役立つ情報を提供します。

例として、const型で定義されたグローバル変数へのアクセスはインライン化できますが、const型のないグローバル変数は実行時に変更される可能性があるため、インライン化できません。

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

実際には、constパフォーマンスは向上しますが、ほとんどの場合、向上しないか、向上しますが、変化は目立たないことに注意してください。の主な有用性constは最適化ではありません。


Steve Jessopは、最初の質問に対するコメントで、言及する価値のある何かをもたらす別の例を示しています。ブロックスコープでは、コンパイラconstは変数のすべての使用を確認できるため、に関係なく、変数が変更されるかどうかを推測し、それに応じて最適化することができます。対照的に、上記の例ではfoo1、他の翻訳単位で変更される可能性があるため、変更されるかどうかを予測することはできません。架空の知覚力のあるウルトラコンパイラーは、プログラム全体を分析して、インラインアクセスが有効かどうかを判断できると思いfoo1ますが、実際のコンパイラーはできません。


@ericcurtinだから、答えの中でコンパイラについては触れなかった。通常、生成されたアセンブリを投稿するときは、コンパイラとバージョンを必ず記載しますが、これはすべての主要な最適化コンパイラが実行する最適化であるため、これが1つのコンパイラに固有であるという印象を与えたくありませんでした。
Praxeolitic 2018年

1
@Acornこれは同じ例ですが、クラスオブジェクトがあります:godbolt.org/z/R-Zfgc。また、この例の変数には外部リンケージがあります。
Praxeolitic

6

私の経験では、

スカラー変数の場合、コンパイラーは値が変更されるたびに判別し、必要な最適化を実行できます。

配列ポインターの場合、constの正確性は、潜在的なエイリアシングの問題が存在する場合に値が実際に一定であることを保証するものではありません。したがって、コンパイラーはconst修飾子のみを使用して最適化を実行することはできません。

最適化を検討している__restrict__場合は、特別な関数修飾子/属性を検討する必要があります:http//gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.