2

C++ の仮想関数のコストについて不満を言う人をよく見かけます。しかし、同じ人々は Java のランタイム ポリモロヒズムについて否定的なことは何も言いません。

C++ で開発されたアプリケーションをホストするランタイムを C++ で開発する必要がある場合は、次のアプローチを取ります。

  1. 「抽象」アプリケーションを表す仮想メソッドを持つ基本クラスがあります。これは、アプリケーションの実行時のビューです。アプリ開発者は基本クラスを継承し、アプリケーションを動的にロード可能な共有ライブラリにコンパイルします。
  2. ランタイムからの「サービス」を表す仮想メソッドを持つ基本クラスがあります。ランタイムはこれらのサービスを実装します。アプリケーションは、これらのインターフェイス クラスを通じてこれらのサービスを使用します。ランタイムはアプリケーションの動的ライブラリをロードし、そのサービスの実装オブジェクトでアプリケーションを初期化します。

アプリケーションとランタイムの両方が互いのハンドルを持ち、仮想メソッド呼び出しを使用して互いに呼び出します。はい、コストがかかりますが、これによりランタイムからアプリを切り離すこともできます。仮想メソッドがない場合、アプリは常にランタイムとのリンク時間依存性を持ちます。

次に、Java で同様のケースを考えてみましょう。Java にも実装が必要なインターフェースがあり、関連するランタイム ポリモーフィズムにも同様のコストがかかるはずです。

Java ランタイム ポリモヒズムに関する私の理解は正しいですか?

また、Java にもコストがかかる場合、なぜ c++ は常に「ああ、仮想関数のコストがあり、仮想関数を使用してアプリケーションの一部を分離するアプローチは確かに悪い」という怒りのコメントを受け取ります。Javaの場合、これらの人々はどこに行きますか? 彼らは何も言わない。

私の質問は、そのようなコメントをどのように処理するかです。C ++を支持する合理的な議論は何ですか?

4

4 に答える 4

1

仮想メソッドの使用における C++ と Java の主な違いは、Java 開発者には選択の余地がないため、この場合、Java 開発者はパフォーマンスへの影響について考えないことです。

また、Java VM は仮想呼び出しを処理するように設計されています。これにはパフォーマンスへの影響がありますが、他に方法がないため測定できません。また、新しい VM は実行時に仮想メソッドをインライン化することもできます。

C++ には履歴があります。C++ は C から派生したもので、初期には動的リンクはありませんでした。時間の経過とともに動的リンクが追加され、このリンク プロセスは互換性のある方法で実行する必要がありました。仮想機能の追加は、これと互換性のある方法で行われました。また、最初の C++ コンパイラは C のプリプロセッサにすぎなかったため、仮想関数を既存の C 構造にマップする必要がありました。

したがって、C++ での仮想関数のパフォーマンスへの影響は、歴史に基づいた主要なものだと思います。

于 2013-06-30T09:29:14.020 に答える
1

ここにはすでに答えがなければならないので、ここに答えを書くことは無駄になるのではないかと心配しています。

それについてあまり「言語の心配」をせずに、Java を使用する人は必ずしも C++ プログラマーほどパフォーマンスに重点を置いているとは限らないと思います。オーバーヘッド"。

仮想関数と非仮想関数の間には確かにいくらかのオーバーヘッドがあります [1] - 非仮想関数は、仮想バージョンではインライン化できない場所でインライン化できる場合があります。しかし、他の選択肢 (スイッチまたは if ステートメントを使用して何をすべきかを決定する) が適切であることはめったになく、設計が少し優れている (仮想関数を呼び出して 2 つの整数を加算するようなものを設計しないでください。タイトなループで呼び出されます - オーバーヘッドがかなり大きくなるので - 数百または数千の整数を加算することを知っている関数を使用してください - もちろん可能であれば)。

[1] オーバーヘッドは、ポインタを間接的に読み取っthisて vtable を見つけ、そこからオフセット X で関数を呼び出すことで構成されます。主なオーバーヘッドは、「より多くのレジスタ」が使用される傾向があり、コードの効率に悪影響を及ぼす可能性があります。

于 2013-06-30T09:09:26.550 に答える