2

次のような関数があります。

const std::string& ConvertToString(Enum e)
{
    static const std::string enumStrings[4] =
    {
        std::string("first"),
        std::string("second"),
        std::string("third"),
        std::string("unknown")
    }

    int enumOrd = static_cast<int>(e);
    if (e < 0 || e > 2)
    {
        return enumStrings[3];
    }

    return enumStrings[enumOrd];
}

さて、問題は、この関数が main() が戻った後に呼び出され、その静的配列が既に破棄されているためにクラッシュしていることです。私はそれを次のように変更したい:

std::string ConvertToString(Enum e)
{
    switch (static_cast<int>(e))
    {
        case 0: return std::string("first");
        case 1: return std::string("second");
        case 2: return std::string("third");
        default: return std::string("unknown");
    }
}

この変更により、この関数を呼び出すコードが壊れる可能性があるかどうか疑問に思っています。問題は考えられません (返されるクラスが const メソッドで卑劣なことをしていない限り、特に const ref -> value の遷移では std::string は問題ないはずですが、多分私は'何かが足りない。

4

2 に答える 2

2

ConvertToString同じオブジェクトを生成するための異なる呼び出しに依存するコードを壊すことができます:

for (std::string::const_iterator it = ConvertToString(first).begin();
     it != ConvertToString(first).end(); ++it) {
   // undefined behavior: cannot compare iterators referring 
   // to two different containers/strings
}

もう 1 つの注意点として、実装が期待どおりに動作しない可能性があります。enum Enum { first, second, third };特に、列挙がコードとして定義されている場合:

if (e < 0 || e > 2) {
   return enumStrings[3];
}

最適化コンパイラによって完全に削除されるunknown可能性があり、関数によって返されることはありません。その理由は、Enum列挙子のビットマスクではない値 (この場合: 0、1、2、3) を列挙が正当に保持できないためです。そうすることは、未定義の動作です。コンパイラは、この知識を使用してコードを最適化し、テスト条件を削除しe < 0たり、テスト条件を単一の に変換したりできe == 3ます。

于 2013-07-16T19:53:14.227 に答える