コードが同等の C 言語よりも遅いことが知られている C++ プログラミング言語の側面はありますか? 明らかに、これは仮想関数や vtable 機能などの OO 機能を除外します。
レイテンシが重要な領域でプログラミングしている場合 (オブジェクト指向機能について心配していない場合) は、基本的な C++ を使い続けることができるのか、それとも C の方が優れているのでしょうか?
コードが同等の C 言語よりも遅いことが知られている C++ プログラミング言語の側面はありますか? 明らかに、これは仮想関数や vtable 機能などの OO 機能を除外します。
レイテンシが重要な領域でプログラミングしている場合 (オブジェクト指向機能について心配していない場合) は、基本的な C++ を使い続けることができるのか、それとも C の方が優れているのでしょうか?
C または C++ 言語標準では、コンストラクトの速度を指定するものはありません (C++ は、コンテナーに適用される一部の操作の時間の複雑さを指定しますが、それは質問の範囲外です)。特定のコンストラクトに対して生成されるコードの速度は、それをコンパイルするために使用されるコンパイラと、それが実行されるシステムによって異なります。
同じセマンティクスを持つ有効な C および有効な C++ である特定のコード構成の場合、どちらかが他方よりも高速であるべきという根本的な理由はありません。しかし、コンパイラの開発者がもう少し賢ければ、一方が他方よりも高速になる可能性があります。
それは、「同等」の意味によって異なります。C の stdio.h を C++ の iostream と比較すると、stdio.h の操作は一般的に高速です (状況によってはかなり高速です)。しかし、有効な C としてもコンパイルされる C++ のサブセットで記述されたコードについて話している場合、生成されるマシン コードはおそらく同一です。
一例として、C++ にはキーワード がありませんrestrict
。正しく使用すると、コンパイラがより高速なコードを生成できる場合があります。
restrict
が得られることはほとんどありませんが、restrict
キーワードが使用されていなくても、C++ または C コンパイラが (インライン展開後に) 必要な条件が適用され、それに応じて動作することを推測できる場合がたくさんあります。restrict
orを提供する場合があります。__restrict
しかし、時折 (または一部のドメインでは非常に一般的)、restrict
非常に優れた最適化であり、それが Fortran を使用し続けている理由の 1 つだと私は言います。restrict
これは確かに、C と C++ の両方で厳格なエイリアシング ルールが適用されている理由の 1 つです。これにより、より限定された一連の状況と同じ最適化の機会が得られます。
これを「カウント」するかどうかは、「同等のコード」と見なす範囲によって異なります。restrict
それを有効に使用するプログラムの意味を変更することは決してありません。コンパイラはそれを自由に無視できます。したがって、それを使用するプログラム (C コンパイラーの目) と使用しないプログラム (C++ の場合) を「同等」として説明するのは無理があります。プログラマーはそれを使用する前にそれが正しいことを確認する必要があるため、バージョンをrestrict
作成するのに、より多くの (おそらくわずかに多くの) プログラマーの努力が必要でした。
つまり、有効なCと有効なC++であり、両方で同じ意味を持つプログラムがありますが、実装はC++標準によって何らかの形で制約され、C実装よりも遅く実行されます。答えはかなり確信しています「いいえ」です。つまり、標準 C では利用できるが標準 C++ では利用できない潜在的なパフォーマンス調整があるということであれば、答えは「はい」です。
微調整から何らかの利益が得られるかどうかは別の問題です。両方の言語で利用可能な異なる最適化を使用して、同じ量の労力に対してより多くの利益が得られるかどうかは別の問題です。上の言語はまだ別のものです。C と C++ コードの間で相互運用するのは笑えるほど簡単なので、C++ を好む何らかの理由がある場合は、好みのコーディング方法を変更する最適化と同様に、C への切り替えは通常、プロファイラーが指示したときに行うことです。あなたの機能は遅すぎます。
また、自明でないデストラクタを持つ型を決して使用しないと仮定して、例外の可能性がパフォーマンスを犠牲にするかどうか、何らかの形で自分自身を納得させようとしています。実際には、おそらく可能であると思います(これは「使用しないものにお金を払わない」という原則と矛盾しています)-fno-exceptions
。C++ の実装により、コストはかなり低くなります (そして、ほとんどがコードではなく、rodata にあります) が、ゼロというわけではありません。レイテンシが重要なコードは、バイナリ サイズが重要なコードである場合とそうでない場合があります。
繰り返しになりますが、「同等の」コードの意味に依存する可能性がありますg++ -fno-exceptions
-C++コードがCと同じくらい良いのですが、ある意味でC++標準は私にいくらかの費用がかかります.
最後に、C++ ランタイム自体にも起動コストがかかります。これは、「同じ」プログラムの C ランタイム起動コストと必ずしも同じではありません。一般に、厳密には必要のないものを削除することで、両方のコストを削減するためにハックすることができます。しかし、それは努力です。実装が毎回完全にそれを行うとは限りません。したがって、C++ では、使用しないものにお金を払わないというのは厳密には真実ではありません。それが一般的な原則ですが、それを達成することは実装の品質の問題です。
多くの C プログラマーが好んで考えていることとは反対に、C++ では多くの場合、設計を大幅に犠牲にすることなく、よりタイトで高速なコードを記述できます。
C の対応するものよりも遅い C++ のものは考えられません。仮想関数は除外されません。
レイテンシクリティカルとは、可能な限り高速という意味ですか、それとも単にすべてを予測可能な時間内に実行する必要があるという意味ですか?
2 番目のケースの場合、予測可能な時間内に実行されないのは とnew
だけdelete
ですtry/catch
。組み込みプログラミングでは、このような呼び出しを回避するためのディレクティブがあります。それ以外の場合、特に C++11 では、一部の処理が高速であり (std::sort は C の sort() よりも高速)、一部の処理はわずかに低速です。
しかし、C++ よりも高い抽象化レベルが得られ、C スタイルのバグが発生しません (malloc()
対応する のない典型的なバグのようにfree()
) 。
C と C++ の交差点である言語を使用している場合、そのコードを C コンパイラと C++ コンパイラでコンパイルするときのパフォーマンスの違いは、純粋に実装の品質の問題です。一方が他方より速くなければならない理由はありません。
もちろん、現実の世界では、C++ を使用している場合は、C と C++ の共通点に対して C++ が持つ追加機能の両方を使用してプログラミングし、C とは異なるイディオムを使用してプログラミングします。逆に、C を使用している場合は、少なくとも C++ で使用するものとは非常に異なるイディオムを使用しており、Steve が述べたように、restrict
キーワード、VLA、またはポインターへのポインターなど、C++ にはない最新の C 言語の追加機能を使用している可能性もあります。 VLA 型、または複合リテラル。これらの機能により、状況によってはパフォーマンスが大幅に向上する可能性がありますが、私の経験では、C++ よりも C を選択するほとんどの人がそうする理由にはなりません。
私の考えでは、主な違いはイディオムです。C では、リスト ノードとリスト ノードに個別のラッパー オブジェクトを使用するのではなく、リストに保持されている構造体に直接 next/prev ポインターを配置して、リンクされたリストを作成するのが慣用的です。C では、文字配列として文字列の要素を直接反復処理するのが慣用的です。C では、動的ストレージを割り当てるのではなく、可能な限り完全に自動ストレージに存在するオブジェクトを操作するのが慣用的です。等々。これらの慣用的な違いは、C コードが C++ よりも高速で軽量になる主な理由です。
もちろん、必要に応じて、C++ でも同じイディオムを使用できます。これは、ほとんどの C イディオムに必要な言語構造のほとんどが、C と C++ の交差点に存在するためです。また、必要に応じて C++ の追加機能を使用することもできます。しかし、非慣用的な C++ コードを作成することになり、他の C++ プログラマーから多くの批判を受ける可能性があります...
C++ には、C に直接相当するコードの方が高速である、または実際に保守しやすいコードはありません。