14

3 つの異なる型パラメーターでインスタンス化される C++ テンプレート クラスがあります。これらの型の 1 つだけのためにクラスが持つ必要があり、他の 2 つの型では決して呼び出されないメソッドがあります。

そのメソッドのオブジェクト コードは 3 回 (テンプレートがインスタンス化されるすべての型に対して) 生成されますか、それともオブジェクト コードは (実際に使用される型に対して) 1 回だけ生成されますか?

4

3 に答える 3

24

仮想メンバー関数はクラス テンプレートがインスタンス化されるときにインスタンス化されますが、非仮想メンバー関数は呼び出された場合にのみインスタンス化されます。

これは、C++ 標準の [temp.inst] でカバーされています (C++11 では、これは §14.7.1/10 です。C++14 では、これは §14.7.1/11 であり、C++17 では§17.7.1/9 です。以下 C++17 からの抜粋)

実装は、関数テンプレート、変数テンプレート、メンバー テンプレート、非仮想メンバー関数、メンバー クラス、クラス テンプレートの静的データ メンバー、またはconstexprif ステートメントのサブステートメントを暗黙的にインスタンス化してはなりません (9.4.1) 。 、そのようなインスタンス化が必要でない限り

また、一部のメンバー関数が特定のテンプレート パラメーターに対してインスタンス化できない場合でも、クラス テンプレートをインスタンス化できることに注意してください。例えば:

template <class T>
class Xyzzy
{
public:
    void CallFoo() { t.foo(); }  // Invoke T::foo()
    void CallBar() { t.bar(); }  // Invoke T::bar()

private:
    T t;
};

class FooBar
{
public:
    void foo() { ... }
    void bar() { ... }
};

class BarOnly
{
public:
    void bar() { ... }
};

int main(int argc, const char** argv)
{
    Xyzzy<FooBar>  foobar;    // Xyzzy<FooBar> is instantiated
    Xyzzy<BarOnly> baronly;   // Xyzzy<BarOnly> is instantiated

    foobar.CallFoo();         // Calls FooBar::foo()
    foobar.CallBar();         // Calls FooBar::bar()

    baronly.CallBar();        // Calls BarOnly::bar()

    return 0;
}

Xyzzy::CallFoo() は BarOnly::foo() のようなものがないためインスタンス化できませんが、これは有効です。この機能は、テンプレート メタプログラミング ツールとしてよく使用されます。

ただし、テンプレートの「インスタンス化」は、生成されるオブジェクト コードの量とは直接相関しないことに注意してください。これは、コンパイラ/リンカーの実装によって異なります。

于 2008-10-08T14:59:05.560 に答える
2

コンパイラと設定に依存すると思います。たとえば、MSVC6 ではすべてが生成されたと思いますが、VS2005 では生成されません。仕様では、コンパイラはそうすべきではないと述べていますが、現実の世界では、実際のコンパイラに依存しています (たとえば、MSVC6 のブーストには多くの回避策があります)。/opt:ref が有効になっている場合、リンカは参照されていない関数を削除できます (VS の場合、他のコンパイラには同等のオプションが存在します)。

于 2008-10-08T18:43:25.750 に答える
1

通常、はい。

コンパイラが本当に知っているのは、プログラムが各クラスの少なくとも 1 つのインスタンスを作成できるということだけです。しかし、それらのインスタンスで何をするかはわかりません。したがって、コードはほぼ確実に生成されます。

とはいえ、問題のメソッドが仮想ではなく、呼び出されない場合、リンカ通常のデッド コード削除機能を使用してそれらを削除できます。したがって、生成された (およびコンパイルされた) コードは、最終的な EXE には含まれません。

また、これはすべて同じではないため、使用されている C++ コンパイラに大きく依存します。

于 2008-10-08T14:46:44.290 に答える