C++ が C と比べて本質的に遅いということはありませんが、慣用的な C++ コードは、同じタスクを実行する慣用的な C コードよりもはるかに遅く、重くなる傾向があります。ここでは慣用的な言葉が重要です。C++ でタスクを実行する場合とまったく同じ方法でタスクを実行する C コードを作成すると、同じように遅くなります。一方、隠れたコストが一般的に C++ で忍び寄る場所を認識している場合は、コストを最小限に抑え、多くのコストをかけずに C++ の利点を得る努力をすることができます。
何よりもまず、動的メモリ割り当てです。C では、すべて明示的であるため (またはmalloc
または、割り当てられたオブジェクトを返すサードパーティ ライブラリ関数の呼び出し)。C++ では、オブジェクトのストレージ期間が自動である多くのクラス オブジェクトでは、コンストラクターで非表示の割り当てが行われるため、依然として動的メモリ割り当てが発生します。優れた C++ STL (またはサードパーティ ライブラリ) の実装では、オブジェクト自体の内部に小さなバッファーを含め、大きなバッファーが必要な場合にのみ動的割り当てを実行することで、このコストの多くを回避できますが、実際にこれを行うものはほとんどありません。(私が間違っていなければ、llvm の libc++ はそうしますが、GCC の libstdc++ はそうではありません。) これは実装の品質の問題であり、多くの場合、独自のコードでは制御できないため、影響を最小限に抑えるためにここでできる主なことは次のとおりです。自動オブジェクトが動的メモリを割り当てる可能性を認識し、また、必要以上に作成しないようにします (たとえば、可能な場合はポインターや参照を使用します)。これには、コードに対する他の利点もあります。
もう 1 つの大きな領域は、文字列の処理です。snprintf
慣用的な C では、文字列は、または類似のものを使用して一挙に構築されます。C++ およびより強力な文字列クラス/型を持つ他の多くの言語では、文字列の連結 (ピースごとの構築) は慣用的です。これは非常に非効率的であり、メモリの断片化は言うまでもなく、複数の割り当て/割り当て解除手順、コピーなどにつながります。C++ のベスト プラクティスがどのようなものかはわかりませんが (私は C++ に精通していません)、この影響を最小限に抑える方法はあるはずです。
そしてもちろん、最も一般的なのは隠しコードです。これは一種のキャッチオールです。C++ では、見たことのない多くの余分なコードが実行されるコードを簡単に記述できます。コンストラクタ/デストラクタ、オーバーロードされた演算子、およびテンプレートが最も明白な原因です。繰り返しになりますが、C で同じ方法を実行したい場合、コストは同じになりますが、違いは、C では自分で作成する必要があるため、すぐにコストが表示されることです。