5

静的キャストを使用して継承階層をナビゲートする方が動的キャストを使用するよりも効率的であると述べているC++に関する1冊の本を見ました。

例:

#include <iostream>
#include <typeinfo>

using namespace std;

class Shape { public: virtual ~Shape() {}; };
class Circle : public Shape {};
class Square : public Shape {};
class Other {};

int main() {
    Circle c;

    Shape* s = &c; // Upcast: normal and OK

    // More explicit but unnecessary:
    s = static_cast<Shape*>(&c);
    // (Since upcasting is such a safe and common
    // operation, the cast becomes cluttering)

    Circle* cp = 0;
    Square* sp = 0;

    // Static Navigation of class hierarchies
    // requires extra type information:
    if(typeid(s) == typeid(cp)) // C++ RTTI
        cp = static_cast<Circle*>(s);
    if(typeid(s) == typeid(sp))
        sp = static_cast<Square*>(s);
    if(cp != 0)
        cout << "It's a circle!" << endl;
    if(sp != 0)
        cout << "It's a square!" << endl;

    // Static navigation is ONLY an efficiency hack;
    // dynamic_cast is always safer. However:
    // Other* op = static_cast<Other*>(s);
    // Conveniently gives an error message, while
    Other* op2 = (Other*)s;
    // does not
} ///:~

ただし、動的キャストと静的キャスト(上記で実装)の両方で、このようなナビゲーションを機能させるにはRTTIを有効にする必要があります。動的キャストでは、クラス階層が多態的である必要があります(つまり、少なくとも1つの仮想関数を持つ基本クラス)。
静的キャストのこの効率の向上はどこから来るのですか?この本は、動的キャストがタイプセーフなダウンキャストを行うための好ましい方法であると述べています。

4

4 に答える 4

9

static_cast それ自体はRTTIを必要としません- typeid(そうするようにdynamic_cast)必要ですが、それは完全に異なる問題です。ほとんどのキャストは、コンパイラに「私を信じて、私が何をしているのか知っている」と言っているだけですdynamic_cast。例外は、実行時にチェックして失敗する可能性があることをコンパイラに要求することです。それがパフォーマンスの大きな違いです。

于 2009-09-05T05:37:00.880 に答える
7

可能であれば、タイプのスイッチをオンにしない方がはるかに優れていますこれは通常、関連するコードを、サブタイプごとに異なる方法で実装される仮想メソッドに移動することによって行われます。

class Shape {
public:
    virtual ~Shape() {};
    virtual void announce() = 0;  // And likewise redeclare in Circle and Square.
};

void Circle::announce() {
    cout << "It's a circle!" << endl;
}

void Square::announce() {
    cout << "It's a square!" << endl;
}

// Later...
s->announce();

変更できない既存の継承階層を使用している場合は、訪問者パターンを調べて、タイプ切り替えのより拡張可能な代替手段を探してください。

詳細: static_cast RTTIは必要ありませが、RTTIを使用したダウンキャストは安全ではなく、未定義の動作(クラッシュなど)につながる可能性があります。 dynamic_castRTTI情報をチェックする(したがって必要とする)ため、安全ですが低速です。古いCスタイルのキャストは、コンパイル時エラーで反対するstatic_cast完全に無関係な型に静かにキャストするため、さらに安全ではありません。static_cast

于 2009-09-05T05:36:41.057 に答える
5

静的キャスト(およびtypeidチェック)を使用すると、中間タイプにダウンキャストできません(子は父親から派生し、祖父から派生します。祖父から父親にダウンキャストすることはできません)。使用法はもう少し制限されます。typeidチェックなしのstatic_castは、パフォーマンスの正確さを犠牲にしているので、彼らが何を言っているかがわかります。

パフォーマンスのために正確さを犠牲にする彼はどちらにも値しない

そしてもちろん、いくつかのCPU命令が切実に必要であり、改善を探す場所が他になく、実際に何をしているかについて安全であり、その唯一の場所を測定した(右?)状況があります。パフォーマンスを向上させるには、dynamic_castの代わりにstatic_castを使用します...その場合、設計またはアルゴリズムを作り直すか、より優れたハードウェアを入手する必要があります。

rtti + static_castを使用して課す制限は、このトリックを使用していくつかのCPU命令を取得したすべての場所をやり直さないと、後で新しい派生クラスでコードを拡張できないことです。そのリワーク自体は、おそらく、取得したCPU時間よりも多くの時間(より高価なエンジニアリング時間)を要します。いずれにせよ、ダウンキャストに費やされる時間が目立つ場合は、j_random_hackerが示唆するように設計を作り直してください。これにより、設計とパフォーマンスの両方が向上します。

于 2009-09-05T10:02:06.323 に答える
1

dynamic_casttypeidチェックを行わず、キャストが成功しなかった場合、NULLを返します。 static_cast成功します(そして、最終的なクラッシュなどの未定義の動作につながります)。それはおそらく速度の違いです。

于 2009-09-05T05:32:13.120 に答える