事実

神話の後には事実が続きます。したがって、C++ に関する半分真実であり、真実ではないステートメントの領域を残します。

この投稿での私の論拠は C++98 に基づいています。それには 2 つの理由があります。まず、MISRA C++ ガイドラインと「パフォーマンスに関するテクニカル レポート C++」の両方が、C++11 標準よりも前に書かれています。次に、古典的な C++ が神話を反駁するのに十分強力であることを示します。

MISRA C++

現在の MISRA C++:2008 ガイドラインは、M によって発行されました。 オトル 業界 S ソフトウェア R 適格性 A 協会。これらは、1998 年の MISRA C ガイドラインに基づいています。元々は自動車業界向けに設計されたもので、航空、軍事、医療分野で重要なソフトウェアを実装するためのデファクト スタンダードになりました。 MISRA C として、MISRA C++ は C++ の安全なサブセットのガイドラインを説明しています。

このサブセットは、ドキュメント、必須、または勧告として分類される 200 以上のルールで構成されています。

  • ドキュメント:
    • 開発者の必須要件
    • 派生は許可されていません
  • 必須:
    • 開発者の必須要件
    • 正式な派生を提起する必要があります
  • 勧告:
    • 可能な限り従うべきです
    • 正式な派生は必要ありませんが、考慮される場合があります

ルールは、C++ コア言語とライブラリに関するものです。わかりやすくするために、MISRA C++ のルールをいくつか紹介します。

  • 不要な構文
    • プロジェクトには、到達不能なコードが含まれていてはなりません。 (必須)
    • プロジェクトには、未使用の変数が含まれていてはなりません。 (必須)
  • アセンブラ
    • アセンブラのすべての使用法を文書化する必要があります。 (ドキュメント)
  • 算術
    • 浮動小数点演算の使用について文書化する必要があります。 (ドキュメント)
  • 言語
    • コードは C++03 標準に準拠する必要があります (注:C++98 への小さな追加)。 (必須)
  • コメント
    • コードを「コメントアウト」するために C コメントを使用してはなりません。 (必須)
    • コードを「コメントアウト」するために C++ コメントを使用してはなりません。 (勧告)
  • ポインタ変換
    • NULL を整数値として使用してはなりません。 (必須)
  • 複数の基本クラス
    • 仮想ベースからクラスを派生させてはなりません。 (勧告)
  • 仮想関数
    • オーバーライドする各仮想関数は、virtual キーワードで宣言する必要があります。 (必須)
  • 例外処理
    • 例外は、エラー処理にのみ使用されます。 (ドキュメント)
  • テンプレート
    • テンプレートの部分的および明示的な特殊化はすべて、主要なテンプレートの宣言と同じファイルで宣言する必要があります。 (必須)
  • マクロの置き換え
    • # および ## 演算子は使用しないでください。 (勧告)
  • 図書館
    • C ライブラリは使用しないものとします。 (必須)
    • すべてのライブラリ コードは MISRA C++ に準拠する必要があります。(ドキュメント)

静的コード分析ツールを使用して、これらおよび他のすべての MISRA C++ ルールを検証できます。

重要なシステムでの C++ の使用に関する MISRA C++ ルールから、どのような結論を引き出すことができますか? MISRA C++ では、1 つの機能も言語全体も除外されていません。

MISRA C++ はさらに一歩進んで、重要なシステムにおける C++ の重要性がますます重要になっている理由を強調しています。 (1.1 重要なシステムでの C++ の使用):

  • C++ は、多くの組み込みシステムに不可欠な、高速で低レベルの入出力操作を適切にサポートします。
  • アプリケーションの複雑さが増しているため、アセンブリ言語よりも高級言語を使用する方が適切です.
  • C++ コンパイラは、C と同様のサイズと RAM 要件でコードを生成します。

しかし、1 つの小さなダウナーが残っています。 MISRA C++ は、従来の C++ に基づいています。最新の C++ には、組み込みシステム向けに提供できる機能が他にもたくさんあります。残念ながら、MISRA C++ は C++ の標準化と足並みを揃えることができません。しかし、オンライン フォーラムでの議論から、彼らがギャップを埋めたいと考えていることはわかっています。

C++ パフォーマンスに関するテクニカル レポート

ワーキング グループ WG 21 は、その年に ISO/IEC TR 18015 を発行しました。タイトルはあまり面白くないように聞こえますが、C++ 機能のパフォーマンス数値を取得したい場合、このドキュメントは究極の情報源です。この文書は、その懸念を直接的に表現しています。

  • さまざまな C++ 言語およびライブラリ機能の使用によって暗示される時間とスペースのオーバーヘッドのモデルを読者に提供する
  • パフォーマンスの問題について広まっている神話を暴くため
  • パフォーマンスが重要なアプリケーションで C++ を使用するためのテクニックを紹介する
  • C++ 標準言語とライブラリ機能を実装して効率的なコードを生成するテクニックを紹介する

200 ページを超える論文の著者は、Dave Abrahams、Howard Hinnand、Dietmar Kühl、Dan Saks、Bill Seymour、Bjarne Stroustrup、Detlef Vollmann などの有名な C++ 専門家です。

このドキュメントの範囲は、C++ の機能、そのオーバーヘッドと使用法、C++ での効率的なライブラリの作成、組み込みシステムでの C++ の使用法、およびハードウェアと通信するための C++ のインターフェイスです。特に、C++ の機能とそのオーバーヘッドと使用法が、この投稿の主なトピックです。

C++ の機能、オーバーヘッド、および使用法

著者は、5 つの異なるコンパイラを備えた 3 つのコンピューター アーキテクチャを分析に使用しています。彼らは、さまざまな最適化オプションを持つコンパイラを使用しています。非常に注目に値する結果のアイデアだけをお伝えします。

  • 名前空間
    • サイズとパフォーマンスに大きなオーバーヘッドがない
  • 型変換演算子
    • C++ のキャスト const_cast、static_cast、および reinterpret_cast は、サイズもパフォーマンスも C pedant と変わりません。
    • 実行時に実行される dynamic_cast にはオーバーヘッドがあります . (注:変換には C pedant はありません。)
  • 継承
    • クラス
      • 仮想関数を持たないクラスは、構造体と同じ大きさです。
      • 仮想関数を持つクラスには、ポインターと仮想関数テーブルのオーバーヘッドがあります。これらは約 2 ~ 4 バイトです。
    • 関数呼び出し
      • 非仮想、非静的、および非インライン関数の呼び出しは、フリー関数の呼び出しと同じくらいコストがかかります。
      • 仮想関数の呼び出しは、テーブルに格納されているポインターを使用するフリー関数の呼び出しと同じくらいコストがかかります。
      • クラス テンプレートの仮想関数は、サイズのオーバーヘッドを引き起こす可能性があります。 (注:テンプレート パラメーターに依存しない関数は、基本クラスで抽出する必要があります。したがって、テンプレート パラメーターに依存しない機能は、すべての派生クラス テンプレート間で共有できます。)
      • インライン化 関数を使用すると、パフォーマンスが大幅に向上し、C マクロのパフォーマンスに近くなります。
    • 多重継承
      • 時間やスペースのオーバーヘッドが発生する可能性があります。
      • 仮想基本クラスには、非仮想基本クラスと比較してオーバーヘッドがあります。
  • ランタイム型情報 (RTTI)
    • 必要なクラスごとに約 40 バイトが追加されます。
    • typeid 呼び出しは非常に遅いです。これは、実装の品質によるものと思われます。
    • dynamic_cast を使用した実行時の変換が遅い。レポートによると、実装の品質にも起因するはずです。
  • 例外処理
    • 例外を処理する方法は 2 つあります。これらはコードとテーブル戦略です。コーディング戦略では、例外を処理するために追加のデータ構造を移動および管理する必要があります。テーブル戦略には、テーブルに実行コンテキストがあります。
      • コーディング戦略には、スタックとランタイムのサイズ オーバーヘッドがあります。実行時のオーバーヘッドは約 6% です。このオーバーヘッドは、例外がスローされなくても存在します。
      • テーブル戦略には、プログラムのサイズや実行時のオーバーハンドはありません。 (注:そのステートメントは、例外がスローされなかった場合にのみ保持されます。)テーブル戦略は実装がより困難です。
  • テンプレート
    • テンプレートのインスタンス化ごとに、新しいクラス テンプレートまたは関数テンプレートを取得します。したがって、単純にテンプルを使用すると、コードが肥大化する可能性があります。最新の C++ コンパイラは、テンプレートのインスタンス化の数を大幅に削減できます。部分的または完全な特殊化を使用すると、テンプレートのインスタンス化を減らすことができます。

詳細、正確な数、いくつかの追加トピックは、レポートで直接読むことができます:TR18015.pdf.

」にも小さなダウナーがあります。 このレポートは 2006 年のものです。特に C++11 には、より高速なコードを記述するための多くの機能があります。この論文の著者である Detlef Vollmann 氏に、Meeting C++ で更新の予定があるかどうか尋ねました。現代の C++ へのレポート. ビャルネ ストロストルプへの彼の要求は、彼には時間がないという結果をもたらしました. 理解できるが、少しダウナー.

auto による自動型推論については、次の投稿で書きます。安全性が重要なシステムと自動車の共通点は何ですか?たくさん!