3

これは、私が本番環境で実行しているコードのミニチュア バージョンです。私の実際のコードは、gcc コンパイラーと Intel コンパイラーの下で異なる動作をすることがわかりました。私の最善の推測は、未定義の動作です。次のサンプル コードを検討してください。

#include <iostream>

struct baseFunctor{
    virtual double operator()(double x) const = 0;
};

class mathObj{
    const baseFunctor *tmp1, *tmp2;
public:
    void set(const baseFunctor& b1, const baseFunctor& b2){
        tmp1 = &b1;
        tmp2 = &b2;
    }
    double getValue(double x){
        return (tmp1->operator()(x) + tmp2->operator()(x));
    }
};

int main () {
    mathObj obj;

    struct squareFunctor: public baseFunctor {
        double operator()(double x) const { return x*x; }
    };
    struct cubeFunctor: public baseFunctor {
        double operator()(double x) const { return x*x*x; }
    };

    obj.set(squareFunctor(), cubeFunctor());
    std::cout << obj.getValue(10) << std::endl; 
    return 0;
}

未定義obj.set(squareFunctor(), cubeFunctor());の動作を引き起こす可能性はありますか?

4

1 に答える 1

5

はい、ステートメントの最後に破棄される一時的な値へのポインターを格納し、それらを使用しているため、間違いなくそうです。破壊されたオブジェクトの使用は未定義の動作です。

値を個別に作成してから呼び出す必要がありsetます。

cubeFunctor cf;
squareFunctor sf;

obj.set(sf, cf);

ファンクターを値で格納しても (テンプレートを使用しない限り)、この問題を解決できないことに注意してください。

また、補足として、次のように変更できgetValueます

return (*tmp1)(x) + (*tmp2)(x);

少し見栄えを良くするため(それでも動的ディスパッチを取得できます)。

于 2012-09-26T01:23:52.777 に答える