9

私が次のようなクラスを持っているとしましょう

class Empty{
    Empty(int a){ cout << a; }
}

そして、私はそれを使用してそれを呼び出します

int main(){
    Empty(2);
    return 0;
}

これにより、「空の」オブジェクトを作成するためにスタックにメモリが割り当てられますか?明らかに、引数はスタックにプッシュする必要がありますが、余分なオーバーヘッドは発生しません。基本的に私はコンストラクターを静的メンバーとして使用しています。

私がこれをしたい理由はテンプレートのためです。実際のコードは次のようになります

template <int which>
class FuncName{
    template <class T>
    FuncName(const T &value){
        if(which == 1){
            // specific behavior
        }else if(which == 2){
            // other specific behavior
        }
    }
};

これで私は次のようなものを書くことができます

int main(){
    int a = 1;
    FuncName<1>(a);
}

のタイプを指定する必要がなく、1つのテンプレートパラメータを特殊化できるようにしますT。また、コンパイラーがコンストラクター内の他のブランチを最適化することを望んでいます。これが本当かどうか、またはチェックする方法を誰かが知っているなら、それは大いにありがたいです。また、テンプレートをその状況に投げても、「空のクラス」の問題は上から変わらないと思いましたよね?

4

3 に答える 3

17

Stroustrupの引用:

空のクラスのサイズがゼロではないのはなぜですか?2つの異なるオブジェクトのアドレスが異なることを確認します。同じ理由で、「new」は常に個別のオブジェクトへのポインタを返します。検討:

class Empty { };

void f()
{
    Empty a, b;
    if (&a == &b) cout << "impossible: report error to compiler supplier";

    Empty* p1 = new Empty;
    Empty* p2 = new Empty;
    if (p1 == p2) cout << "impossible: report error to compiler supplier";
}   

空の基本クラスを別のバイトで表す必要がないという興味深いルールがあります。

struct X : Empty {
    int a;
    // ...
};

void f(X* p)
{
    void* p1 = p;
    void* p2 = &p->a;
    if (p1 == p2) cout << "nice: good optimizer";
}

この最適化は安全であり、最も役立つ可能性があります。これにより、プログラマーは空のクラスを使用して、オーバーヘッドなしで非常に単純な概念を表すことができます。現在のコンパイラの中には、この「空の基本クラスの最適化」を提供しているものがあります。

于 2010-01-06T21:45:38.400 に答える
2

試してみてください。多くのコンパイラは、出力を最適化するように求められたときに、そのような一時オブジェクトを排除します。

逆アセンブルが複雑すぎる場合は、そのようなオブジェクトの数が異なる2つの関数を作成し、それらを囲むオブジェクトのスタック位置に違いがあるかどうかを確認します。たとえば、次のようになります。

void empty1 ( int x )
{
    using namespace std;

    int a;
    Empty e1 ( x );
    int b;

    cout << endl;
    cout << "empty1" << endl;
    cout << hex << int ( &x ) << " " << dec << ( &x - &a ) << endl;
    cout << hex << int ( &a ) << " " << dec << ( &a - &b ) << endl;
}

empty8次に、8つの空が作成された関数と比較して実行してみてください。x86のg++では、空のアドレスを取得すると、スタック上のxとaの間の位置が取得されるため、出力にxが含まれます。オブジェクトのストレージが、ソースコードで宣言されているのと同じ順序になるとは限りません。

于 2010-01-06T21:44:53.500 に答える
2

状況によってはそうではないかもしれません。あなたが言うなら:

Empty e;
Empty * ep = & e;

その後、明らかに物事を割り当てる必要があります。

于 2010-01-06T21:39:03.680 に答える