7

C ++で新しい型を定義したいのですが、これは単なるプリミティブ型です(私の例ではint、任意の型にすることができます)。NodeIdこの例では型を呼び出します。

私はただ使うことができましたtypedef int NodeIdNodeIds のデフォルト値が必要なので、 を使用します#define NULL_NODE_ID -1

typedefここで、関数isValid()と null を構築するデフォルトのコンストラクターを許可する代わりに、クラスを定義する方が良いと思いますNodeId

class NodeId
{
    int value;
public:
    inline NodeId() : value(-1) {}
    inline NodeId(int value) : value(value) {}
    inline operator int() {return value;}
    inline bool isValid() {return value != -1;}
    //...
};

2 番目の方法を使用することで生じるパフォーマンス上の欠点はありますか?

4

4 に答える 4

6

実際、これがおそらく遅くなる可能性がある2つの理由があります。

まず、初期化されていないNodeIdを作成する方法はありません。通常、それは良いことです。しかし、次のようなコードがあると想像してください。

NodeId nodeid;
foo.initializeNodeId(&nodeid);

実際には必要のない追加の割り当てを行うことになります。

特別なコンストラクターを追加することで、これを修正できます。Foo :: createNodeId()を作成する方がおそらくはるかに優れているので、Foo :: initializeNodeId(&NodeId)は必要ありませんが、Fooの定義を制御しない場合は、それが不可能な場合があります。

次に、NodeIdはコンパイル時の定数式ではありません。dasblinkenlightが示唆しているように、これはパフォーマンスの問題を引き起こすよりも、コードが合法でないという問題を引き起こす可能性がはるかに高くなりますが、両方とも可能です。(なぜですか?intを使用している場合、実行時に実行時に実行できるコードをコンパイラに挿入させている可能性があるためです。これは、NodeIdというクラスの問題である可能性が高いわけではありません… )。

幸い、C ++ 11を使用している場合は、constexprを使用して修正できます。また、コードを正当なC ++ 03にしたい場合は、マクロを使用して処理できます。

また、dasblinkenlightが指摘しているように、2つの方法でconstが欠落しています。

最後に、クラス定義内で定義されているメソッドに「インライン」を記述する理由はありません。それらはすでに本質的にインラインです。

すべてを一緒に入れて:

#if __cplusplus > 201000L
#define CONSTEXPR_ constexpr
#else
#define CONSTEXPR_
#endif

class NodeId
{
    int value;
public:
    struct Uninitialized {};
    CONSTEXPR_ NodeId() : value(-1) {}
    CONSTEXPR_ NodeId(Uninitialized) {}      
    CONSTEXPR_ NodeId(int value) : value(value) {}
    CONSTEXPR_ operator int() const {return value;}
    CONSTEXPR_ bool isValid() const {return value != -1;}
    //...
};

これで、追加の-1割り当てのコストを回避するために、これを行うことができます。

NodeId nodeId(NodeId::Uninitialized());
foo.initializeNodeId(&nodeid);

そしてこれは、NodeIdを非型テンプレートパラメータとして合法的に使用するには、次のようにします。

myClassTemplate<NodeId(3)> c;

または、これは、コンパイラが合法的にxを4に初期化できることを確認するためです。

int x = 3;
x += NodeId(1);
于 2012-07-03T22:47:04.930 に答える
4

比較的新しいコンパイラを使用する場合、生成されるコードは同じである必要があります。コンパイラーは、これらのメンバー関数のインライン化に問題がないはずです。本当に疑問がある場合は、いつでも実行可能ファイルを逆アセンブルできます。

于 2012-07-03T22:24:46.060 に答える
3

コンパイラの最適化設定により、コンパイラがすべてをインライン化できる場合、パフォーマンスの違いはありません。私が見つけられる唯一の欠点は、このクラスのオブジェクトに基づく式がコンパイル時の定数として適格でなくなる可能性があることです。これは、テンプレートプログラミングで重要になる可能性があります。それ以外は、実行時のコストなしでさらに明確になります。


PSあなたはconstあなたoperator intとに欠けていますisValid

inline operator int() const {return value;}
inline bool isValid() const {return value != -1;}
于 2012-07-03T22:28:02.593 に答える
1

これを他のプログラミング言語で使用される可能性のあるライブラリにすることを計画している場合 (これを C++ DLL に書き込む場合など) typedef int、.

たとえば、API の Python ラッパーまたは Java ラッパーを作成している場合、クラスと型を移植するための頭痛の種はそれほど多くありません。次に、心配する必要があるのは、のビットサイズですint

于 2012-07-03T22:54:51.027 に答える